Repository files navigation

ElectrideFlow - High-Throughput Inorganic Electride Discovery Workflow Accelerated by Generative Models and Hierarchical Prescreening

A four-stage intelligent workflow for high-throughput inorganic electride discovery on HPC clusters:

  1. Chemical Exploration - Generative AI models (MatterGen) explore composition space targeting electride-favorable chemistries
  2. Stability Screening - MatterSim (MLP) pre-screening filters structures by energy above hull before expensive DFT calculations
  3. Electride Identification - Coarse DFT relaxation with ELF & PARCHG topological analysis to identify electride candidates
  4. Refinement - Tight DFT relaxation with refined convex hull analysis for final candidate validation

Table of Contents


Features

MatterSim pre-screening - filter structures by energy_above_hull before VASP (saves 40-60% computation)
Batch processing - reuses MatterSimCalculator across structures for GPU memory efficiency
Parallel prescreening - split prescreening across multiple GPU nodes for faster throughput
Stable phases only - queries only on-hull MP phases for accurate, fast convex hull analysis
Smart caching - single global cache files (mp_mattersim.json, mp_vaspdft.json) handle overlapping systems
PyXtal symmetrization - automatic structure symmetrization for better VASP convergence
Unified SPE workflow - SC-PARCHG-ELF in single job (75% fewer SLURM jobs)
Batch submission - submit n structures at a time, auto-submit more as jobs complete
Dynamic monitoring - check status and submit new jobs automatically
Local JSON database - no network dependencies, works on HPC
Smart workflow - Pre-screen → Relax → SPE (SC + PARCHG + ELF sequential)
PARCHG analysis - band-edge charge density for accurate electride identification
Two-step filtering - initial analysis saves all, stricter filtering for candidates
Fast symmetry - PyXtal-based (14× faster than AFLOW)
Query-able database - ase db commands for candidate exploration
Pymatgen input generation - INCAR, POSCAR, POTCAR, KPOINTS
Bader analysis - identify electride candidates with topological analysis
Interrupt-safe - resume from any interruption
HPC-friendly - workflow manager runs as SLURM job


Quick Start

1. Setup Environment

# On HPC login nodecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# Copy files from your local machine:# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow orchestration# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Monitor workflow progress# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# Load CUDA runtime (check your HPC's available versions, need >= 11.8)
module load cuda/11.8
# Create conda environment
conda create -n mattersim python=3.10
conda activate mattersim
# Install PyTorch with matching CUDA version FIRST# (adjust cu118 to match your loaded CUDA module)
pip install torch==2.5.1+cu118 torchvision==0.20.1+cu118 torchaudio==2.5.1+cu118 \
--index-url https://download.pytorch.org/whl/cu118
pip install torch_scatter==2.1.2+pt25cu118 torch_sparse==0.6.18+pt25cu118 \
torch_cluster==1.6.3+pt25cu118 torch_spline_conv==1.2.2+pt25cu118 \
-f https://data.pyg.org/whl/torch-2.5.1+cu118.html
pip install torch-geometric==2.7.0 pytorch-lightning==2.0.6
# Install pymatgen/mp-api (pinned versions for MP API compatibility)
pip install pymatgen==2024.10.29 mp-api==0.43.0 monty==2024.7.30 emmet-core==0.84.10
# Install other dependencies
pip install numpy>=2.0 ase==3.23.0 pyxtal==1.1.1
# Install MatterSim last (--no-deps to avoid overriding torch versions)
pip install mattersim --no-deps
# Then install any missing mattersim deps that don't conflict:
pip install torch-ema torch-runstats torchmetrics
# Set environment variables in ~/.bashrcecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc

2. Pre-screening with MatterSim (NEW Step)

# Option A: Single GPU job (for small datasets)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--device cuda \
--compositions-per-job 400
# Optional: Add --pure-pbe flag to filter MP entries to pure GGA-PBE only# (default is mixed PBE/PBE+U which is recommended for best accuracy)# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Automatically splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# When done, check results
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# View cache files (single global files with chemsys field)
ls -lh ./VASP_JOBS/mp_mattersim.json
cat ./VASP_JOBS/mp_mattersim.json | jq '.[0]'# (Optional) Visualize results and extract CIF files
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

3. VASP Workflow (Run After Pre-screening)

# Submit VASP workflow manager (processes structures that passed pre-screening)cd /scratch/$USER/vaspflow
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Check job status
squeue -u $USER
tail -f workflow_manager_<JOBID>.out

4. Monitor Progress

cd /scratch/$USER/vaspflow
conda activate mattersim
# Check workflow manager job
squeue -u $USER# View workflow manager log
tail -f workflow_manager_<JOBID>.out
# Overall workflow status
python workflow_status.py ./VASP_JOBS/workflow.json
# Composition breakdown
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# Running VASP jobs
python workflow_status.py ./VASP_JOBS/workflow.json --running
# Failed structures
python workflow_status.py ./VASP_JOBS/workflow.json --failed

5. Analyze Results

# Submit electride analysis as SLURM job
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# When complete, view all analyzed structures
cat electride_analysis.csv
# Filter with stricter criteria to get high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# View filtered candidates
cat electride_candidates.csv
# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Query database for specific criteria
ase db electride_candidates.db 'e_above_hull<0.05'

Complete Setup Guide

Initial Setup (One-time)

# 1. SSH to HPC
ssh your_cluster
# 2. Create conda environment with all dependencies
conda create -n mattersim python=3.10
conda activate mattersim
conda install -c conda-forge pymatgen mp-api
pip install mattersim ase
# 3. Setup workspacecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# 4. Upload workflow scripts from your local machine# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Status monitoring# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# 5. Make scripts executable
chmod +x *.py *.sh
# 6. Set environment variablesecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc
# 7. Verify setup
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
echo"MP API Key: $MP_API_KEY"

Starting a Workflow

# 1. SSH to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# 2. Run pre-screening first (MatterSim + MP)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# Wait for pre-screening to complete (~1-2 hours for 100 structures)# Check results:
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 2b. (Optional) Visualize and extract stable structures
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 3. Submit VASP workflow manager (processes passing structures)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20 \
--max-structures 0
# 4. Monitor (optional)
squeue -u $USER# Check job status
tail -f workflow_manager_*.out # View log# You can now safely log out - workflow runs as SLURM job!

Resuming After Interruption

# SSH back to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if workflow manager is still running
squeue -u $USER| grep vaspflow_manager
# If not running, resubmit (database persists!)
bash run_workflow.sh --max-concurrent 20
# It automatically resumes from saved state in workflow.json

Workflow Overview

Architecture

MatterGen Structures
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 1: Pre-screening (prescreen.py + MatterSim) │
│ - SLURM job on compute node │
│ - Relax structures with MatterSim ML potential │
│ - Query MP for competing phases (cached per chemical system)│
│ - Compute energy_above_hull │
│ - Output: prescreening_stability.json │
│ - Filter: only E_hull < 0.1 eV/atom proceed to VASP │
└──────────────────────────────────────────────────────────────┘
↓
prescreening_stability.json
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 2: VASP Workflow (workflow_manager.py) │
│ - SLURM job on compute node │
│ - Initialize workflow database (JSON) │
│ - Batch submission loop: │
│ * Submit up to max_concurrent VASP jobs │
│ * Each structure: Relax → SC → PARCHG* → ELF (sequential)│
│ (* PARCHG only for semiconductors, band gap > 0.01 eV) │
│ * Monitor job completion every 60s │
│ * Submit new structures as slots free up │
└──────────────────────────────────────────────────────────────┘
↓
Analyze ELF + PARCHG Results (Bader analysis)
↓
Identify Electride Candidates

Job Chain Per Structure

  1. Pre-screening (MatterSim): Quick stability check → energy_above_hull
  2. Relax (VASP): Optimize geometry → CONTCAR
  3. SC (Self-Consistent): Accurate electronic structure → CHGCAR, WAVECAR, vasprun.xml
  4. PARCHG (all materials): Band-decomposed charge density → PARCHG-band0, PARCHG-band1, PARCHG-e0025, PARCHG-e05, PARCHG-e10
  5. ELF: Calculate electron localization → ELFCAR (PARCHG files copied here for analysis)

Directory Structure

/scratch/$USER/VASP_JOBS/
├── Li10B1N3/
│ ├── Li10B1N3_s001/
│ │ ├── Relax/
│ │ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ │ ├── job.sh
│ │ │ ├── CONTCAR (after completion)
│ │ │ ├── VASP_DONE (or VASP_FAILED)
│ │ │ └── vasp_*.out/err
│ │ └── SPE/ ← Unified SC-PARCHG-ELF directory
│ │ ├── job.sh ← Single SLURM job for all stages
│ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ ├── generate_parchg_incars.py ← Helper script (copied by workflow)
│ │ ├── SC_DONE, PARCHG_DONE ← Stage markers
│ │ ├── VASP_DONE (or VASP_FAILED) ← Final completion marker
│ │ ├── INCAR-SC, OSZICAR-SC, vasprun.xml-SC ← SC outputs
│ │ ├── INCAR-PARCHG-e0025, INCAR-PARCHG-e05, INCAR-PARCHG-e10
│ │ ├── INCAR-PARCHG-band0, INCAR-PARCHG-band1
│ │ ├── PARCHG.tar.gz ← Compressed PARCHG files
│ │ ├── INCAR-ELF
│ │ ├── ELFCAR ← ELF output
│ │ ├── ELF_DONE ← ELF stage marker
│ │ └── vasp_*.out/err
│ └── Li10B1N3_s002/
├── workflow.json # Job tracking database
├── prescreening_stability.json ← Pre-screening results
├── mp_mattersim.json ← Cached MP stable phases (MatterSim energies)
├── mp_vaspdft.json ← Cached MP stable phases (DFT energies)
└── electride_candidates.json # Analysis results

Workflow States

Each structure progresses through these states in workflow_manager.py:

PENDING (structure passed pre-screening, ready for VASP)
↓
RELAX_RUNNING → RELAX_DONE → SC_RUNNING → PARCHG_RUNNING → ELF_RUNNING → ELF_DONE
↓ ↓ ↓ ↓ ↓ ↓
RELAX_FAILED (skip) SC_FAILED PARCHG_FAILED ELF_FAILED (success)
Note: SC_RUNNING, PARCHG_RUNNING, and ELF_RUNNING are all part of one SPE job
State transitions happen automatically as stage markers are detected

Note: Pre-screening (MatterSim + MP hull analysis) is done separately by prescreen.py. Only structures that pass pre-screening (E_hull < threshold) are loaded into workflow_manager.py.

Key behaviors:

  • Only structures that passed pre-screening are processed
  • Reduced SLURM jobs: 2 jobs per structure (1 Relax + 1 SPE) instead of 8 jobs
  • SPE job runs sequentially: SC -> PARCHG (5 energy windows) -> ELF in one script
  • Stage markers: SC_DONE, PARCHG_DONE, VASP_DONE track progress within SPE job
  • State transitions: Workflow manager detects markers and transitions states automatically
  • PARCHG for ALL materials: Following HT-electride methodology
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied)
  • Workflow manager automatically submits next structure when slots free up
  • Failed jobs don't block other structures
  • Max concurrent limit applies to total running structures

SPE Workflow Architecture

The unified SPE (SC-PARCHG-ELF) workflow uses a clean separation of concerns:

Python (workflow_manager.py) handles:

  • INCAR/POSCAR/POTCAR/KPOINTS for Relax, SC, ELF jobs
  • Structure loading from CIF files and symmetrization
  • Database state tracking and job orchestration
  • Directory structure creation

Helper script (generate_parchg_incars.py) handles:

  • PARCHG INCAR generation (requires parsing vasprun.xml-SC)
  • Band index calculation from NELECT and SOC parameters
  • FFT grid extraction (NGXF, NGYF, NGZF)
  • Called from bash after SC completes

Bash (job.sh in SPE/) handles:

  • Sequential execution: SC → PARCHG (5 types) → ELF
  • File copying between stages (CHGCAR-SC, WAVECAR-SC reused)
  • PARCHG output renaming (PARCHG → PARCHG-e0025, etc.)
  • PARCHG compression (PARCHG-* → PARCHG.tar.gz) to save disk space
  • Cleanup between stages to prevent VASP issues
  • Stage marker creation (SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE)

Why this design:

  • PARCHG is the ONLY calculation requiring runtime VASP output parsing
  • Keeps Python code IDE-friendly (no embedded heredocs)
  • Helper script is testable standalone
  • Other INCARs are straightforward pymatgen calls (no external scripts needed)

Monitoring

Option 1: Workflow Status Tool (Recommended)

# Overall summary
python workflow_status.py ./VASP_JOBS/workflow.json

Shows:

  • Total structures
  • Status breakdown (PENDING, RELAX_RUNNING, SC_RUNNING, etc.)
  • Currently running count
  • Completion percentage

Additional views:

# Running jobs with SLURM job IDs
python workflow_status.py workflow.json --running
# Failed structures (for debugging)
python workflow_status.py workflow.json --failed
# Composition-level summary
python workflow_status.py workflow.json --compositions
# Recently completed structures
python workflow_status.py workflow.json --completed --limit 20
# Filter by specific state
python workflow_status.py workflow.json --details --state SC_RUNNING

Option 2: Reattach to Tmux

# See live workflow output
tmux attach -t vaspflow
# View, then detach: Ctrl+B, then D

Option 3: Check SLURM Queue

# Check running jobs
squeue -u $USER# Check job history
sacct -S $(date --date="7 days ago" -I) -u $USER# Detailed job info
scontrol show job <JOBID>

Option 4: Manual Inspection

# View database directly
cat ./VASP_JOBS/workflow.json | jq '.structures | to_entries | map({id: .key, state: .value.state})'# Check specific job directorycd ./VASP_JOBS/Li10B1N3/Li10B1N3_s001/Relax
ls -lh
tail vasp_*.out
tail OSZICAR

Analyzing Results for Electride Candidates

After ELF calculations complete, analyze structures for electride characteristics using Bader topological analysis on both ELFCAR and PARCHG files.

New in v2.0: Incremental analysis with MatterSim e_above_hull integration, PyXtal database storage, and stricter candidate filtering.

Step 1: Initial Analysis (All Structures)

Recommended: Run analysis as a SLURM job (not on login node):

# Submit analysis job with defaults
bash submit_analysis.sh
# Custom settings
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# View results when complete
cat electride_analysis.csv

Output:

  • electride_analysis.csv - All analyzed structures with interstitial volumes
  • electride_data.db - PyXtal database with all structures

Step 2: Filter High-Quality Candidates

Apply stricter volume thresholds to identify high-quality electride candidates:

# Filter with default thresholds (20 ų)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# Custom thresholds (stricter)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 25 \
--min-band 25

Filtering Criteria:

  • max(e0025, e05, e10) >= min-energy (default: 20 ų)
  • max(band0, band1) >= min-band (default: 20 ų)
  • Removes duplicate structures
  • Adds PyXtal symmetry information (space groups)

Output:

  • electride_candidates.db - Filtered high-quality candidates with symmetry
  • electride_candidates.csv - CSV table for quick viewing

Step 3: Extract CIF Files

Extract CIF files for the filtered candidates:

# Extract from filtered database
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Output: electride_CIF/*.cif - One CIF file per candidate

Step 4: Query Database

Use ase db to query and filter candidates:

# View all candidates
ase db electride_candidates.db
# Sort by space group (high symmetry first)
ase db electride_candidates.db \
formula,space_group_number,e_above_hull \
-s space_group_number-
# Filter by stability (< 50 meV/atom)
ase db electride_candidates.db 'e_above_hull<0.05'# Show interstitial volumes
ase db electride_candidates.db \
formula,e0025,e05,e10,band0,band1,e_above_hull
# Cubic structures (space group >= 195)
ase db electride_candidates.db 'space_group_number>=195'# High interstitial volume (e0025 > 50 ų)
ase db electride_candidates.db 'e0025>50'

What the Analysis Does

Initial Analysis (analyze.py):

  1. Reads ELFCAR - electron localization function from VASP SPE directory
  2. Extracts PARCHG files from PARCHG.tar.gz (5 types):
    • PARCHG-band0: Valence band maximum (VBM)
    • PARCHG-band1: Second highest occupied band (VBM-1)
    • PARCHG-e0025: Energy window [-0.025, 0.025] eV around Fermi level
    • PARCHG-e05: Energy window [-0.5, 0.025] eV
    • PARCHG-e10: Energy window [-1.0, 0.025] eV
  3. Runs Bader analysis on ELFCAR and each PARCHG file
  4. Filters interstitial electrons - sites far from atoms with high localization
  5. Reports volumes of interstitial electron density (ų) for each type
  6. Adds stability data - reads e_above_hull from prescreening_stability.json
  7. Extracts spacegroup - from CONTCAR using PyXtal (adaptive tolerance)
  8. Saves to database - stores all structures in electride_data.db

Filtering (filter_comb_db.py):

  1. Applies volume thresholds - only keeps structures with substantial interstitial volumes
  2. Symmetrizes structures - uses PyXtal with adaptive tolerance (coarse→fine)
  3. Removes duplicates - identifies and filters redundant structures
  4. Adds space group info - from PyXtal symmetry analysis
  5. Creates unified database - electride_candidates.db with structures + volumes
  6. Exports CSV - electride_candidates.csv for quick viewing

Key Features (v2.0)

Incremental Analysis:

  • Automatically skips already-analyzed structures from CSV and database
  • Run repeatedly as new ELF calculations complete without re-processing
  • Perfect for monitoring ongoing workflows

Enhanced Electride Criteria:

  • Old criteria: ANY of (e0025 > 0 OR e05 > 0 OR e10 > 0 OR band0 > 0)
  • New criteria: ALL of (e0025 > 0 AND e05 > 0 AND e10 > 0 AND band0 > 0)
  • More stringent to reduce false positives

DFT Integration:

  • Reads DFT energy_above_hull from compute_dft_e_hull.py output
  • Results sorted by stability (lowest e_above_hull first)
  • Most stable electride candidates rise to the top

PyXtal Database:

  • Saves all analyzed structures to electride_data.db
  • Adaptive symmetrization (tolerances: 1e-5 to 0.5)
  • P1 fallback ensures 100% save success
  • Query-able for advanced analysis

Analysis Parameters

analyze.py:

  • --threshold: Minimum ELF value for electride detection (default: 0.6)
  • --bader-exe: Path to Bader executable (default: bader in PATH)
  • --output: Output CSV file name (default: electride_analysis.csv)
  • --pyxtal-db: PyXtal database file (default: electride_data.db)
  • --prescreening: MatterSim stability JSON (default: ./VASP_JOBS/prescreening_stability.json)
  • --workers: Number of parallel workers (default: CPU count)

filter_comb_db.py:

  • --min-energy: Minimum for max(e0025, e05, e10) in ų (default: 20)
  • --min-band: Minimum for max(band0, band1) in ų (default: 20)
  • --output: Output database (default: electride_candidates.db)
  • --output-csv: Output CSV (default: electride_candidates.csv)

Understanding Results

Initial Analysis (electride_analysis.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045
Li10B1N4_s003,Li10B1N4,0.00,0.00,0.00,5.28,0.00,12,0.068

Columns:

  • formula: Structure ID
  • composition: Chemical formula
  • e0025, e05, e10: Interstitial volumes (ų) from energy windows
  • band0, band1: Interstitial volumes (ų) from band-specific charges
  • spacegroup: PyXtal space group (1 = P1 fallback)
  • e_above_hull: MatterSim energy above hull (eV/atom)

Electride Criteria:

  • (e0025 > 0 OR e05 > 0) AND (e10 > 0 OR band0 > 0)

Filtered Candidates (electride_candidates.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045

Additional Filtering:

  • max(e0025, e05, e10) >= 20 ų (substantial energy window volume)
  • max(band0, band1) >= 20 ų (substantial band-specific volume)
  • Duplicates removed
  • Space group from PyXtal symmetry analysis

Interpreting volumes (in ų):

  • > 20: High-quality electride (passes filtering)
  • 0-20: Weak electride (filtered out by default)
  • High across multiple columns: Strong, robust electride character

Example interpretation:

  • Li10B1N4_s001: High-quality electride (all volumes > 20 ų, stable)
  • Li10B1N4_s002: Moderate electride (volumes > 12 ų, borderline)
  • Li10B1N4_s003: Not electride (very low volumes)

Sorting:

  • Both CSVs sorted by e_above_hull (low → high)
  • Most thermodynamically stable candidates appear first

Console output during analysis:

Total ELF_DONE: 100
Semiconductors (with PARCHG): 15
Metals (ELFCAR only): 85
(All structures analyzed with PARCHG in SPE workflow)
Analyzing: Li10B1N4_s001 (VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE)
Spacegroup: 166
*** ELECTRIDE CANDIDATE *** (e0025=32.62, e05=31.82, e10=31.31, band0=35.11, band1=0.00)
Analyzing: Li10B1N4_s003 (VASP_JOBS/Li10B1N4/Li10B1N4_s003/SPE)
Spacegroup: 139
Not electride (e0025=0.00, e05=0.00, e10=0.00, band0=5.28, band1=0.00)

Filter output:

======================================================================
Filtering Electride Database with Stricter Criteria
======================================================================
Criteria:
max(e0025, e05, e10) >= 20.0 ų
max(band0, band1) >= 20.0 ų
Processing structures...
Added 100 structures...
Using P1 fallback for Ba8S7_s024
Added 200 structures...
Filtering Summary:
Input structures: 6134
Filtered out (below thresholds): 4512
Duplicates removed: 89
Failed to process: 0
Added to output database: 1533

Incremental Analysis Workflow

# Day 1: 50 ELF calculations done
bash submit_analysis.sh
# Output: 50 structures analyzed# → electride_analysis.csv (50 structures)# → electride_data.db (50 structures)# Filter to get high-quality candidates
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 25 high-quality)# electride_candidates.csv# Day 2: 30 more ELF calculations done (total 80)
bash submit_analysis.sh
# Output: Only 30 new analyzed (skips existing 50)# → electride_analysis.csv updated (80 total, re-sorted)# → electride_data.db updated (80 total)# Re-filter with updated data
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 40 high-quality)# Day 3: 20 more ELF calculations done (total 100)
bash submit_analysis.sh
# Output: Only 20 new analyzed# → Final electride_analysis.csv (100 structures)# Final filtering
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: Final electride_candidates.db (e.g., 50 high-quality)# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Benefits:

  • Incremental analysis saves time (only analyzes new structures)
  • Filtering is fast (~2 min) and can be adjusted without re-running Bader
  • Database is query-able at any stage

Direct Analysis (Advanced)

The analysis uses Electride.py internally via analyze.py. For manual testing:

# Test on single structure (SPE workflow)cd VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE
python3 ../../../../Electride.py . --bader-exe ~/apps/Bader/bader
# Run full analysis with all options
python3 analyze.py \
--db VASP_JOBS/workflow.json \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv \
--pyxtal-db electride_data.db \
--prescreening VASP_JOBS/prescreening_stability.json \
--workers 32
# Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20

Requirements:

  • ELFCAR file (generated by VASP with LELF=True in SPE/)
  • PARCHG.tar.gz (5 files compressed, automatically extracted during analysis)
  • Bader executable (download from: https://theory.cm.utexas.edu/henkelman/code/bader/)
  • (Optional) prescreening_stability.json for MatterSim e_above_hull values

Output Files

Initial Analysis:

  1. electride_analysis.csv: All analyzed structures with volumes
  2. electride_data.db: PyXtal database with all structures
  3. electride_analysis_detailed.log: Full console output

Filtered Candidates:

  1. electride_candidates.csv: High-quality candidates (CSV table)
  2. electride_candidates.db: PyXtal database with filtered structures + volumes
  3. electride_CIF/: Directory with CIF files for candidates

Performance

Analysis (analyze.py):

  • Incremental mode: Only analyzes new structures (minutes for 30 new structures)
  • Full analysis: ~5-10 minutes per structure (PARCHG extraction + Bader analysis)
  • Database saves: ~1 second per structure (with adaptive tolerance)
  • Parallel processing: Scales with CPU cores (32 cores recommended)

Filtering (filter_comb_db.py):

  • Time: ~2 minutes for 6000 structures
  • PyXtal symmetry: ~0.02 sec per structure (vs AFLOW: ~0.45 sec)
  • Speedup: 14× faster than AFLOW-based workflow
  • Duplicate removal: Automatic during processing

DFT Energy Above Hull Calculation

After VASP relaxations complete, compute DFT-level thermodynamic stability using your VASP energies combined with Materials Project DFT energies for competing phases.

Energy Method Comparison

Compare energies between different calculation methods to validate pre-screening accuracy and diagnose any systematic biases:

# Run comparison (requires dft_stability_results.json)
bash run_compare_energy_method.sh \
--vasp-jobs ./VASP_JOBS \
--outlier-threshold 0.5
# Monitor job
squeue -u $USER| grep compare_energy
tail -f compare_energy_method_*.out
# Results will be in: VASP_JOBS/energy_method_comparison.json# Plots: mp_phases_comparison_*.png, generated_structures_comparison_*.png

What it compares:

  1. MP On-Hull Phases: MatterSim energies vs MP raw DFT energies
  2. Generated Structures: MatterSim energies vs VASP-DFT energies

Important: The generated structures comparison now uses dft_stability_results.json as the single source of truth for VASP energies. This ensures exact consistency with hull_comparison plots (same structures, same outlier filtering).

Key metrics:

  • Pearson correlation between methods
  • Mean Absolute Error (MAE)
  • Systematic bias detection
  • Helps diagnose non-linear hull behavior

Usage

# Submit DFT hull calculation (after VASP relaxations complete)
bash run_dft_e_hull.sh \
--vasp-jobs ./VASP_JOBS \
--output dft_stability_results.json \
--prescreen-results ./VASP_JOBS/prescreening_stability.json
# Monitor job
squeue -u $USER| grep dft_e_hull
tail -f dft_e_hull_*.out
# Hull comparison (MatterSim vs DFT) is automatically generated# if --prescreen-results is provided to compute_dft_e_hull.py# Results will be in: VASP_JOBS/hull_comparison.json# Plots: hull_comparison_scatter.png, hull_comparison_residuals.png

What It Does

  1. Scans for completed VASP relaxations (RELAX_DONE or later states)
  2. Extracts VASP energies from vasprun.xml
  3. Queries MP for stable phases only (is_stable=True) - much faster than querying all phases
  4. Uses single cache file (mp_vaspdft.json) with automatic subsystem handling
  5. Computes DFT energy_above_hull for each structure using PDEntry
  6. Outputsdft_stability_results.json with decomposition products

Output Format

{
"summary": {
"total_structures": 100,
"processed_successfully": 95,
"failed": 5,
"energy_reference": "DFT uncorrected (VASP-PBE + MP stable phases only)",
"mp_phase_selection": "stable_only (is_stable=True)",
"mp_functional_filter": "mixed_pbe_pbeU"
},
"results": [
{
"structure_id": "Li10B1N4_s001",
"composition": "Li10B1N4",
"chemsys": "B-Li-N",
"vasp_energy_per_atom": -3.45678,
"dft_energy_above_hull": 0.023,
"decomposition_products": "Li3N (0.714) + BN (0.286)",
"num_mp_stable_phases": 18,
"error": null
}
]
}

Validation: MatterSim vs DFT Hull Comparison

The compute_dft_e_hull.py script automatically validates pre-screening accuracy by comparing MatterSim vs DFT hull values when --prescreen-results is provided:

Statistical metrics:

  • Pearson correlation (how well MatterSim predicts DFT)
  • Mean Absolute Error (MAE)
  • Root Mean Square Error (RMSE)

Pre-screening performance:

  • True Positives: Correctly passed (stable in both)
  • False Positives: Incorrectly passed (unstable in DFT, wasted VASP)
  • True Negatives: Correctly filtered (unstable in both)
  • False Negatives: Incorrectly filtered (stable in DFT, missed!)
  • Precision, Recall, F1 Score
  • Computational savings (% VASP avoided)

Output: hull_comparison.json with detailed analysis

When to Use

  • After some VASP relaxations complete: Validate pre-screening accuracy early
  • Before publication: Get accurate DFT stability data
  • To identify outliers: Find structures that were incorrectly filtered/passed

Performance

  • Time: ~1-2 hours for 100 structures (mostly MP API queries)
  • Resources: 8 CPUs, 32GB RAM (for large systems)
  • Caching: Uses MP IDs from pre-screening cache to minimize API calls

Troubleshooting

Workflow Manager Not Running

Symptom: Jobs complete but database still shows RUNNING state

Check if manager job is running:

squeue -u $USER| grep vaspflow_manager

Solution: Restart workflow manager if stopped

bash run_workflow.sh --max-concurrent 10
# It will detect completed jobs and update states

Jobs Not Progressing

Check:

# Check workflow manager job
squeue -u $USER| grep vaspflow_manager
tail -f workflow_manager_*.out
# See what's completed
find ./VASP_JOBS -name "VASP_DONE"| wc -l
find ./VASP_JOBS -name "VASP_FAILED"| wc -l
# Check VASP jobs in queue
squeue -u $USER# Check database state
python workflow_status.py ./VASP_JOBS/workflow.json

Fix: Restart workflow manager if it stopped

bash run_workflow.sh --max-concurrent 10

Failed Jobs

# List all failures
python workflow_status.py workflow.json --failed
# Investigate specific failurecd ./VASP_JOBS/Li10B1N3/Li10B1N3_s003/Relax
tail -50 vasp_*.err
tail -50 OSZICAR
grep -i "error\|killed\|fail" vasp_*.out

Common failure causes:

  • Walltime limit hit (24 hours default)
  • Convergence issues (check OSZICAR)
  • Memory issues (check vasp_*.err)
  • POTCAR problems (check first few lines of vasp_*.out)

Resetting Failed Jobs for Retry

Use reset_failed_jobs.py to reset failed structures and retry them:

# Step 1: List all failed structures to understand what went wrong
python3 reset_failed_jobs.py --list
# Output shows failures grouped by stage:# RELAX_FAILED: 72 structures# SC_FAILED: 4 structures# PARCHG_FAILED: 4 structures# Step 2: Dry run to preview changes (recommended)
python3 reset_failed_jobs.py --dry-run --clean
# Step 3: Reset all failed jobs
python3 reset_failed_jobs.py --clean
# OR reset specific stage only
python3 reset_failed_jobs.py --stage RELAX --clean
python3 reset_failed_jobs.py --stage SC --clean
python3 reset_failed_jobs.py --stage PARCHG --clean
# Step 4: Resume workflow to retry
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10

What it does:

  • RELAX_FAILEDPENDING (retry from scratch)
  • SC_FAILEDRELAX_DONE (retry SC using existing relaxed structure)
  • PARCHG_FAILEDSC_DONE (retry PARCHG using existing SC results)
  • --clean flag removes VASP_FAILED markers for clean restart
  • Creates automatic backup: workflow.json.bak

Important: Investigate failure causes before blindly retrying. Some structures may have fundamental issues (bad geometry, unconverged, etc.) and will fail repeatedly.

POTCAR Not Found

# Check environmentecho$PMG_VASP_PSP_DIR# Verify structure
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
# Set if neededexport PMG_VASP_PSP_DIR=$HOME/apps/PBE64
# Add to ~/.bashrc to persist

Workflow Manager Job Issues

# Check if manager job is running
squeue -u $USER| grep vaspflow_manager
# View manager log
tail -100 workflow_manager_*.out
# Cancel stuck manager job
scancel <JOBID># Restart (database persists!)
bash run_workflow.sh --max-concurrent 10

Jobs Stuck in SLURM Queue

# Check job status
squeue -u $USER -o "%.18i %.9P %.30j %.8T %.10M %.6D %R"# Check why pending
squeue -u $USER -j <JOBID> --start
# Cancel stuck job if needed
scancel <JOBID># Workflow will mark it as failed on next check

Database Corruption

# Backup database
cp workflow.json workflow.json.backup
# Reinitialize (keeps existing directories)
python workflow_manager.py --init-only \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS
# Manually merge completed jobs from backup if needed

Parallel Pre-screening Results Missing

Symptom: After running submit_parallel_prescreen.sh, the prescreening_stability.json file is empty or only contains results from one batch.

Cause: Multiple parallel jobs writing to the same file cause race conditions and data loss.

Solution:

  1. Each batch processes a different subset of compositions using --start-composition (batch 0: comps 0-399, batch 1: 400-799, etc.)
  2. Each batch writes to its own file (prescreening_stability_batch0.json, etc.)
  3. After all jobs complete, merge them with merge_prescreen_batches.py:
# Check that all batch jobs completed
squeue -u $USER| grep prescreen # Should be empty# List batch result files
ls ./VASP_JOBS/prescreening_stability_batch*.json
ls ./VASP_JOBS/prescreening_structures_batch*.db
ls ./VASP_JOBS/mp_mattersim.json # Shared cache (not batch-specific)# Merge all batch results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# OR skip database merge (faster, JSON only)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS --skip-database
# Verify merged results
cat ./VASP_JOBS/prescreening_stability.json | jq '.metadata.total_structures'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Check shared MP cache
ls -lh ./VASP_JOBS/prescreening_structures.db # Check database exists

Prevention: Always run merge_prescreen_batches.py after parallel prescreening jobs complete.


Configuration

Key Parameters

Pre-screening (prescreen.py):

# Single GPU job
python prescreen.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0 \ # Max structures per composition
--batch-size 32 \ # Structures per batch (calculator reuse)
--mp-api-key YOUR_KEY \ # Materials Project API key
--hull-threshold 0.05 \ # E_hull threshold (eV/atom)
--device cuda \ # MatterSim device: cpu or cuda
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Automatically splits compositions across GPU nodes

VASP Workflow (workflow_manager.py):

python workflow_manager.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \ # Max structures running simultaneously
--max-compositions 20 \ # Limit number of compositions (optional)
--max-structures 0 \ # Max structures per composition
--check-interval 60 # Status check interval (seconds)

Recommendations:

  • Pre-screening:
    • --batch-size: 32 for A40/A100 GPUs (48GB VRAM), reduce to 16 for smaller GPUs
    • --hull-threshold: 0.1 eV/atom filters most unstable structures, use 0.05 for stricter filtering
    • --device: Use cuda for GPU acceleration (5-10× faster than CPU)
    • --mp-api-key: Get your free API key at https://next-gen.materialsproject.org/api
    • --pure-pbe: OPTIONAL flag to exclude PBE+U (recommended to OMIT for best accuracy)
      • Default (no flag): Mixed PBE/PBE+U (matches MP phase diagram methodology)
      • With flag: Pure GGA-PBE only (may reduce accuracy for transition metal systems)
    • MP API: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • Large datasets: Use submit_parallel_prescreen.sh to split across multiple GPUs
    • GPU memory: Set export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True in SLURM script
  • VASP Workflow:
  • --max-concurrent: 10-20 for typical HPC cluster
  • --check-interval: 60s is good balance
  • --max-compositions: Omit to process all
    • PyXtal: Structures automatically symmetrized for better convergence

SLURM Settings

Edit create_slurm_script() in workflow_manager.py (lines 163-176):

script=f"""#!/bin/bash#SBATCH --partition=Apus # Change partition#SBATCH --ntasks=32 # Change cores#SBATCH --time=1-00:00:00 # Change walltime (1 day)#SBATCH --mem=64G # Change memoery#SBATCH --output={job_dir}/vasp_%j.out#SBATCH --error={job_dir}/vasp_%j.err

VASP Input Settings

Edit create_vasp_inputs() in workflow_manager.py (lines 129-161):

Relax (line 135-142):

vis=MPRelaxSet(structure, user_incar_settings={
'EDIFF': 1e-6, # Energy convergence'EDIFFG': -0.01, # Force convergence (eV/Å)'NSW': 200, # Max ionic steps'PREC': 'Accurate',
'ISMEAR': 0, # Gaussian smearing'SIGMA': 0.05,
})

SC/Static (line 143-148):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LAECHG': True, # Write core charge'LCHARG': True, # Write CHGCAR
})

ELF (line 149-156):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LELF': True, # Calculate ELF'ADDGRID': True, # Finer FFT grid'NSW': 0, # No ionic steps'IBRION': -1,
})

Electride Detection Parameters

python analyze_completed.py \
--threshold 0.6 \ # ELF threshold (0.5-0.7 typical)
--min-distance 1.5 \ # Min distance from atoms (Å)
--volume-threshold 0.5 # Min interstitial volume (ų)

Performance

Per Structure (typical, 32 cores)

Pre-screening (MatterSim):

  • Relaxation: 10-30s per structure (CPU) or 5-10s (GPU)
  • MP query: One-time per chemical system (~2-5 min, cached)
  • Hull analysis: <1s per structure

VASP calculations:

  • Relax: 2-6 hours
  • SPE job (SC + PARCHG + ELF sequential): 5-10 hours
    • SC: 1-3 hours
    • PARCHG (5 sequential): 2.5-5 hours (5 × 30-60 min)
    • ELF: 1-2 hours
  • Total VASP time: 7-16 hours/structure
  • SLURM overhead: Reduced by 75% (2 jobs instead of 8 jobs per structure)

With pre-screening (filters ~60% structures):

  • Effective time: 3-6 hours/structure (accounting for filtered structures)
  • Savings: 40-60% of total VASP computation time

Example Workflow (100 structures, max_concurrent=10, with pre-screening)

TimeActionRunningCompletedNotes
T=0Pre-screen 100 structures00MatterSim + MP
T=1hPre-screening done0060 pass, 40 filtered out
T=1hSubmit first 10 Relax jobs100Only stable structures
T=5h10 Relax done, submit 10 SPE100SPE = SC+PARCHG+ELF
T=13h10 SPE done, submit new1010~8h per SPE job
...Repeat10...
T=53hAll 60 complete06040 filtered by pre-screening

Wall time: ~53 hours for 100 structures (60 pass pre-screening)
Core-hours: ~24,000 (60 structures × 12.5h avg × 32 cores / 2 efficiency)
SLURM jobs: 120 total (vs 480 with old workflow)
Savings: 40-60% computational time from pre-screening, 75% fewer SLURM jobs


MatterSim Pre-screening

Pre-screening uses the MatterSim ML potential to quickly evaluate thermodynamic stability before running expensive VASP calculations. This is done in a separate step using prescreen.py, which generates prescreening_stability.json with structures that pass the stability threshold.

How It Works

  1. MatterSim Relaxation: Structures relaxed in batches with calculator reuse for GPU memory efficiency
  2. MP Reference Phases Query: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • The modern mp_api.client misses many stable GGA phases needed for accurate hull calculations
    • Strict filtering: only accepts entries with -GGA or -GGA+U suffix in entry_id
    • Uses uncorrected_energy (raw DFT, no MP corrections) to match MatterSim energies
    • Optional --pure-pbe flag to exclude PBE+U (use pure GGA-PBE only)
  3. Re-relax MP Structures: MP GGA structures are re-relaxed with MatterSim for consistent energy reference
  4. Convex Hull: Build phase diagram using MatterSim energies with PDEntry
  5. Output: Generate prescreening_stability.json with structures that pass threshold
  6. VASP Workflow Filter: workflow_manager.py reads prescreening_stability.json and only processes structures with E_hull < threshold (default: 0.1 eV/atom)

Key Optimizations (NEW)

Batch Processing:

  • MatterSimCalculator reused across 32 structures per batch (configurable with --batch-size)
  • Dramatically reduces GPU memory overhead and initialization time
  • Automatic GPU memory cleanup between batches
  • Supports CUDA memory expansion: PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

Complete GGA Coverage with Legacy API:

  • Uses legacy pymatgen.ext.matproj.MPRester instead of modern mp_api.client
  • Modern API misses many stable GGA phases critical for accurate hull calculations
  • Queries ALL GGA/GGA+U entries via get_entries_in_chemsys()
  • Strict suffix filtering: Only accepts entries with -GGA or -GGA+U suffix in entry_id
  • Excludes r2SCAN, SCAN, and entries without explicit functional suffix
  • Uses uncorrected_energy (raw DFT, no MP anion/composition corrections)
  • Optional --pure-pbe flag to exclude PBE+U (for pure GGA-PBE calculations only)
  • More accurate phase diagrams with comprehensive GGA reference phases

Single Global Cache Files:

  • mp_mattersim.json: All MatterSim-relaxed MP phases with chemsys field
  • mp_vaspdft.json: All MP DFT energies with chemsys field
  • Automatically handles overlapping chemical systems (e.g., B-Li-N includes B, Li, N subsystems)
  • No more separate cache directories with duplicate data

Parallel Multi-GPU Processing:

  • submit_parallel_prescreen.sh: Splits compositions across multiple GPU nodes
  • Each batch job writes to unique files:
    • JSON: prescreening_stability_batch0.json, prescreening_stability_batch1.json, ...
    • Database: prescreening_structures_batch0.db, prescreening_structures_batch1.db, ...
  • MP cache is SHARED across all batches using dual-level file locking:
    • Single file: mp_mattersim.json (all batches read/write safely)
    • Cache I/O locking: mp_mattersim.lock prevents file corruption
    • Per-chemsys locking: mp_cache_{chemsys}.lock prevents duplicate MP queries
    • When Batch 0 queries Ba-O, other batches wait for it to finish
    • After Batch 0 completes, other batches read from cache (no duplicate API calls)
    • Lock files auto-cleaned after merge
  • After all jobs complete, run merge_prescreen_batches.py to combine results
  • Command-line configurable (use --help for full options)
  • Configurable compositions per job (default: 400)
  • Linear speedup with number of GPUs
  • Example: 2000 compositions → 5 GPU nodes = 5x faster
  • Critical: File locking ensures safe concurrent access to shared MP cache

PyXtal Symmetrization:

  • Structures automatically symmetrized before MatterSim relaxation
  • Same symmetrization applied to VASP initial structures in workflow_manager.py
  • Improves convergence and consistency between pre-screening and VASP

Configuration

# Option A: Single GPU job (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--device cuda \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Pure GGA-PBE only (omit for best accuracy)# View all options
bash submit_parallel_prescreen.sh --help
# Monitor parallel jobs
squeue -u $USER| grep prescreen
# After all parallel jobs complete, merge batch results
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# This combines:# - prescreening_stability_batch*.json → prescreening_stability.json# - prescreening_structures_batch*.db → prescreening_structures.db# - mp_mattersim.json is already shared (no merging needed)# Options:# --keep-batches: preserve individual batch files (default: delete after merge)# --skip-database: skip database merge, only merge JSON (faster)# Custom options for single GPU
bash run_prescreen.sh \
--batch-size 64 \ # Larger batch (requires more GPU memory)
--hull-threshold 0.05 \ # Stricter threshold (fewer pass)
--device cuda # Use GPU (much faster than CPU)# Check results and cache
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Number of cached MP phases
cat ./VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'# By chemical system# Step 2: Run VASP workflow (automatically filters based on pre-screening)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Note: VASP structures are automatically symmetrized with PyXtal before relaxation# This ensures consistency with pre-screening and improves convergence# By default, workflow_manager.py looks for:# ./VASP_JOBS/prescreening_stability.json## To use a different file:
bash run_workflow.sh --prescreen-results /path/to/custom_results.json
# To skip filtering (process all structures):# (Not recommended - remove prescreening_stability.json first)
bash run_workflow.sh # Will warn if file not found

Performance Impact

Overhead (with optimizations):

  • Single GPU: ~30-60 minutes for 100 structures across 10 chemical systems
  • Parallel (5 GPUs): ~10-15 minutes for same dataset (5x speedup)
  • Batch processing: 3-5x faster than previous per-structure calculator creation
  • Stable phases only: 10-20x faster MP queries (20-50 phases vs 500+ phases)
  • First structure in each chemical system takes longer (MP query + cache)
  • Subsequent structures in same system benefit from shared cache

Cache Efficiency:

  • Single mp_mattersim.json file (~1-5 MB) replaces multiple per-chemsys files
  • Automatic deduplication of overlapping subsystems
  • B-Li-N system includes: B, Li, N, B-Li, B-N, Li-N, B-Li-N (7 subsystems in 1 cache)

Savings:

  • Filters 50-80% of structures (typical)
  • Saves 4-10 VASP hours per filtered structure
  • Net savings: 40-60% of total computation time
  • Additional: Pre-screening itself is 3-5x faster with batch processing

Checking Pre-screening Results

# View pre-screening summary
cat VASP_JOBS/prescreening_stability.json | jq '.summary'# View individual results
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | { id: .structure_id, chemsys: .chemsys, E_hull: .energy_above_hull, passed: .passed_prescreening}'| less
# Count passed vs filtered
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==true)'| jq -s 'length'
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==false)'| jq -s 'length'

Pre-screening Utilities

Visualizing Energy Distribution

Use plot_e_above_hull.py to visualize the energy distribution and verify your threshold:

# Plot histogram of energy_above_hull values
python3 plot_e_above_hull.py \
--input ./VASP_JOBS/prescreening_stability.json \
--output histogram.png \
--bins 100 \
--max-energy 2.0

Extracting Stable Structures

Use extract_stable_structs.py to extract CIF files for structures that passed pre-screening:

# Extract CIF files for structures that passed pre-screening
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

Troubleshooting

All structures filtered out:

  • Threshold may be too strict (try --hull-threshold 0.2)
  • Check if MP API key is working
  • Verify MatterSim is installed correctly

Pre-screening taking too long:

  • Use GPU: --device cuda
  • MP cache should build once per chemical system
  • Check MP API rate limits (built-in backoff)

SLURM Job Management Reference

Basic SLURM Commands

ActionCommand
Submit workflow managerbash run_workflow.sh --max-concurrent 20
Check job queuesqueue -u $USER
Check specific jobsqueue -j <JOBID>
View job logtail -f workflow_manager_<JOBID>.out
Cancel jobscancel <JOBID>
Job historysacct -u $USER
Job detailsscontrol show job <JOBID>

Typical Usage Pattern

# Day 1: Start workflow
ssh your_cluster
cd /scratch/$USER/vaspflow
bash run_workflow.sh --max-concurrent 20
# Note the job ID, then log out# Day 2: Check progress (from anywhere)
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if manager is still running
squeue -u $USER| grep vaspflow_manager
# Check workflow progress
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# View manager log
tail -f workflow_manager_*.out

Files

FilePurpose
prescreen.pyMatterSim pre-screening with batch processing
run_prescreen.shSubmit single-GPU pre-screening wrapper
submit_prescreen.shSLURM script for single-GPU pre-screening
submit_parallel_prescreen.shNEW: Parallel multi-GPU prescreening across nodes
merge_prescreen_batches.pyNEW: Merge parallel batch results into single file
plot_e_above_hull.pyVisualize pre-screening energy distribution
extract_stable_structs.pyExtract CIF files for stable structures
workflow_manager.pyVASP workflow with PyXtal symmetrization
run_workflow.shSubmit workflow wrapper (user-facing)
submit_workflow_manager.shSLURM script for workflow manager
workflow_status.pyStatus checking and reporting
reset_failed_jobs.pyReset failed jobs to retry (RELAX/SC/PARCHG)
compute_dft_e_hull.pyCompute DFT energy_above_hull + MatterSim comparison
run_dft_e_hull.shSubmit DFT hull wrapper (user-facing)
submit_dft_e_hull.shSLURM script for DFT hull calculation
compare_energy_methods.pyCompare MatterSim vs DFT energies (uses dft_stability_results.json)
run_compare_energy_method.shSubmit energy method comparison wrapper
submit_compare_energy_method.shSLURM script for energy method comparison
analyze.pyOrchestrates electride analysis (calls Electride.py)
analyze.shSLURM script for analysis job
Electride.pyBader analysis on ELFCAR + PARCHG files
submit_analysis.shSubmit analysis wrapper (user-facing)
filter_comb_db.pyNEW: Filter candidates with stricter volume criteria + PyXtal symmetry
extract_electride_struct.pyExtract CIF files from filtered database
generate_parchg_incars.pyHelper script to generate PARCHG INCARs from vasprun.xml-SC

Key Features:

  • Unified SPE workflow: SC-PARCHG-ELF run sequentially in one SLURM job (2 jobs per structure vs 8)
  • Simplified directory structure: Relax/ and SPE/ subdirectories (vs 7+ subdirectories)
  • Stage markers: SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE track progress within SPE job
  • Reduced SLURM overhead: 75% fewer jobs submitted to queue
  • Clean code separation: Python for VASP inputs, bash for workflow orchestration
  • Helper script for PARCHG: Standalone script generates PARCHG INCARs (band indices from vasprun.xml-SC)
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied during relaxation)
  • Batch processing: prescreen.py reuses MatterSimCalculator across structures (3-5× faster)
  • Parallel prescreening: submit_parallel_prescreen.sh splits across GPU nodes (linear speedup)
  • Complete GGA coverage: Uses legacy pymatgen.ext.matproj.MPRester for comprehensive GGA/GGA+U phases
  • Strict functional filtering: Only accepts entries with -GGA or -GGA+U suffix (excludes r2SCAN/SCAN)
  • Uncorrected energies: Uses raw DFT energies (no MP corrections) for accurate hull calculations
  • Optional pure-pbe: --pure-pbe flag to filter MP entries to pure GGA-PBE only (exclude PBE+U)
  • Single cache files: mp_mattersim.json and mp_vaspdft.json in VASP_JOBS/ directory
  • PyXtal symmetrization: Automatic structure symmetrization in both prescreening and VASP workflow
  • Two-step electride filtering: Initial analysis saves all data, stricter filtering for high-quality candidates
  • Fast symmetry analysis: PyXtal-based filtering (14× faster than AFLOW)
  • Query-able database: ase db commands for filtering candidates by stability, symmetry, or volumes
  • PDEntry for hulls: Uses PDEntry instead of ComputedEntry for accurate phase diagram analysis
  • reset_failed_jobs.py resets failed VASP jobs to retry them without data loss
  • Integrated hull validation: compute_dft_e_hull.py automatically validates pre-screening accuracy with plots and statistics
  • Energy method comparison: compare_energy_methods.py uses dft_stability_results.json as single source of truth for exact consistency
  • User-friendly wrapper scripts provide consistent interface across all stages

Best Practices

  1. Run pre-screening first with prescreen.py to save 40-60% of VASP computation
  2. Use parallel prescreening (submit_parallel_prescreen.sh) for large datasets (>500 compositions)
  3. Merge batch results with merge_prescreen_batches.py after all parallel jobs complete
  4. Optimize batch size based on GPU memory: 32 for A40/A100 (48GB), 16 for smaller GPUs
  5. Wait for pre-screening to complete before starting VASP workflow
  6. Check pre-screening results (prescreening_stability.json) to verify threshold is appropriate
  7. Inspect cache files (mp_mattersim.json, mp_vaspdft.json) to verify MP data quality
  8. Submit both jobs as SLURM jobs (required on most HPC systems)
  9. Monitor from login node using workflow_status.py instead of viewing logs constantly
  10. Set reasonable max_concurrent (10-20) to avoid queue congestion
  11. Monitor your quota on /scratch periodically (cache files are now much smaller: ~1-5 MB total)
  12. Check failed jobs early to catch systematic issues
  13. Start small (test with 2-3 structures first using --max-compositions 2 --max-structures 2)
  14. Trust PyXtal symmetrization - structures are automatically symmetrized for consistency

Common Workflows

Production Run (Full Scale)

# Step 1: Pre-screening# Option A: Single GPU (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--device cuda \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets >500 compositions)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400
# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Auto-splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor with: squeue -u $USER | grep prescreen# Wait for completion, check and visualize results
cat VASP_JOBS/prescreening_stability.json | jq '.summary'
cat VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'
jq '.results[] | select(.passed_prescreening == true) | {structure_id, energy_above_hull}' VASP_JOBS/prescreening_stability.json
python3 plot_e_above_hull.py --bins 100
# (Optional) Extract stable structures for inspection
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# Step 2: VASP workflow (structures automatically symmetrized with PyXtal)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0 \
--check-interval 120
# Step 3: Analyze electride candidates
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# Step 4: Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# Step 5: Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Step 6: Query and explore
ase db electride_candidates.db
ase db electride_candidates.db 'e_above_hull<0.05' -s space_group_number-

Resume After Interruption

# Check if still running
squeue -u $USER| grep vaspflow_manager
# If stopped, restart - database persists
bash run_workflow.sh --max-concurrent 20

Integration with MatterGen

# 1. Generate structures with MatterGencd~/mattergen_test/ternary_electride
bash generate_ternary_csp.sh
# 2. Transfer to HPC scratchcd /scratch/$USER
cp -r ~/mattergen_test/results/ternary_csp_electrides mattergen_results/
# 3. Run pre-screening (as SLURM job)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Wait for pre-screening to complete
squeue -u $USER| grep prescreen
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 3b. Visualize and extract stable structures (optional)
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 4. Start VASP workflow (as SLURM job)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20
# 5. Monitor and analyze
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# 6. Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# 7. Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# 8. Query candidates
ase db electride_candidates.db 'e_above_hull<0.05'

Credits & References

Credits:

Tools & Libraries:

Key Paper:

@article{zhuComputationalDiscoveryInorganic2019,
title = {Computational {{Discovery}} of {{Inorganic Electrides}} from an {{Automated Screening}}},
author = {Zhu, Qiang and Frolov, Timofey and Choudhary, Kamal},
year = 2019,
month = nov,
journal = {Matter},
volume = {1},
number = {5},
pages = {1293--1303},
issn = {2590-2385},
doi = {10.1016/j.matt.2019.06.017},
}
@misc{tao2026acceleratedinorganicelectridesdiscovery,
title={Accelerated Inorganic Electrides Discovery by Generative Models and Hierarchical Screening}, author={Shuo Tao and Qiang Zhu},
year={2026},
eprint={2601.21077},
archivePrefix={arXiv},
primaryClass={cond-mat.mtrl-sci},
url={https://arxiv.org/abs/2601.21077}, }

About

DFT-HT Workflow for screening inorganic electrides

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

ElectrideFlow - High-Throughput Inorganic Electride Discovery Workflow Accelerated by Generative Models and Hierarchical Prescreening

A four-stage intelligent workflow for high-throughput inorganic electride discovery on HPC clusters:

  1. Chemical Exploration - Generative AI models (MatterGen) explore composition space targeting electride-favorable chemistries
  2. Stability Screening - MatterSim (MLP) pre-screening filters structures by energy above hull before expensive DFT calculations
  3. Electride Identification - Coarse DFT relaxation with ELF & PARCHG topological analysis to identify electride candidates
  4. Refinement - Tight DFT relaxation with refined convex hull analysis for final candidate validation

Table of Contents


Features

MatterSim pre-screening - filter structures by energy_above_hull before VASP (saves 40-60% computation)
Batch processing - reuses MatterSimCalculator across structures for GPU memory efficiency
Parallel prescreening - split prescreening across multiple GPU nodes for faster throughput
Stable phases only - queries only on-hull MP phases for accurate, fast convex hull analysis
Smart caching - single global cache files (mp_mattersim.json, mp_vaspdft.json) handle overlapping systems
PyXtal symmetrization - automatic structure symmetrization for better VASP convergence
Unified SPE workflow - SC-PARCHG-ELF in single job (75% fewer SLURM jobs)
Batch submission - submit n structures at a time, auto-submit more as jobs complete
Dynamic monitoring - check status and submit new jobs automatically
Local JSON database - no network dependencies, works on HPC
Smart workflow - Pre-screen → Relax → SPE (SC + PARCHG + ELF sequential)
PARCHG analysis - band-edge charge density for accurate electride identification
Two-step filtering - initial analysis saves all, stricter filtering for candidates
Fast symmetry - PyXtal-based (14× faster than AFLOW)
Query-able database - ase db commands for candidate exploration
Pymatgen input generation - INCAR, POSCAR, POTCAR, KPOINTS
Bader analysis - identify electride candidates with topological analysis
Interrupt-safe - resume from any interruption
HPC-friendly - workflow manager runs as SLURM job


Quick Start

1. Setup Environment

# On HPC login nodecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# Copy files from your local machine:# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow orchestration# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Monitor workflow progress# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# Load CUDA runtime (check your HPC's available versions, need >= 11.8)
module load cuda/11.8
# Create conda environment
conda create -n mattersim python=3.10
conda activate mattersim
# Install PyTorch with matching CUDA version FIRST# (adjust cu118 to match your loaded CUDA module)
pip install torch==2.5.1+cu118 torchvision==0.20.1+cu118 torchaudio==2.5.1+cu118 \
--index-url https://download.pytorch.org/whl/cu118
pip install torch_scatter==2.1.2+pt25cu118 torch_sparse==0.6.18+pt25cu118 \
torch_cluster==1.6.3+pt25cu118 torch_spline_conv==1.2.2+pt25cu118 \
-f https://data.pyg.org/whl/torch-2.5.1+cu118.html
pip install torch-geometric==2.7.0 pytorch-lightning==2.0.6
# Install pymatgen/mp-api (pinned versions for MP API compatibility)
pip install pymatgen==2024.10.29 mp-api==0.43.0 monty==2024.7.30 emmet-core==0.84.10
# Install other dependencies
pip install numpy>=2.0 ase==3.23.0 pyxtal==1.1.1
# Install MatterSim last (--no-deps to avoid overriding torch versions)
pip install mattersim --no-deps
# Then install any missing mattersim deps that don't conflict:
pip install torch-ema torch-runstats torchmetrics
# Set environment variables in ~/.bashrcecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc

2. Pre-screening with MatterSim (NEW Step)

# Option A: Single GPU job (for small datasets)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--device cuda \
--compositions-per-job 400
# Optional: Add --pure-pbe flag to filter MP entries to pure GGA-PBE only# (default is mixed PBE/PBE+U which is recommended for best accuracy)# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Automatically splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# When done, check results
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# View cache files (single global files with chemsys field)
ls -lh ./VASP_JOBS/mp_mattersim.json
cat ./VASP_JOBS/mp_mattersim.json | jq '.[0]'# (Optional) Visualize results and extract CIF files
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

3. VASP Workflow (Run After Pre-screening)

# Submit VASP workflow manager (processes structures that passed pre-screening)cd /scratch/$USER/vaspflow
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Check job status
squeue -u $USER
tail -f workflow_manager_<JOBID>.out

4. Monitor Progress

cd /scratch/$USER/vaspflow
conda activate mattersim
# Check workflow manager job
squeue -u $USER# View workflow manager log
tail -f workflow_manager_<JOBID>.out
# Overall workflow status
python workflow_status.py ./VASP_JOBS/workflow.json
# Composition breakdown
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# Running VASP jobs
python workflow_status.py ./VASP_JOBS/workflow.json --running
# Failed structures
python workflow_status.py ./VASP_JOBS/workflow.json --failed

5. Analyze Results

# Submit electride analysis as SLURM job
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# When complete, view all analyzed structures
cat electride_analysis.csv
# Filter with stricter criteria to get high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# View filtered candidates
cat electride_candidates.csv
# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Query database for specific criteria
ase db electride_candidates.db 'e_above_hull<0.05'

Complete Setup Guide

Initial Setup (One-time)

# 1. SSH to HPC
ssh your_cluster
# 2. Create conda environment with all dependencies
conda create -n mattersim python=3.10
conda activate mattersim
conda install -c conda-forge pymatgen mp-api
pip install mattersim ase
# 3. Setup workspacecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# 4. Upload workflow scripts from your local machine# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Status monitoring# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# 5. Make scripts executable
chmod +x *.py *.sh
# 6. Set environment variablesecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc
# 7. Verify setup
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
echo"MP API Key: $MP_API_KEY"

Starting a Workflow

# 1. SSH to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# 2. Run pre-screening first (MatterSim + MP)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# Wait for pre-screening to complete (~1-2 hours for 100 structures)# Check results:
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 2b. (Optional) Visualize and extract stable structures
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 3. Submit VASP workflow manager (processes passing structures)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20 \
--max-structures 0
# 4. Monitor (optional)
squeue -u $USER# Check job status
tail -f workflow_manager_*.out # View log# You can now safely log out - workflow runs as SLURM job!

Resuming After Interruption

# SSH back to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if workflow manager is still running
squeue -u $USER| grep vaspflow_manager
# If not running, resubmit (database persists!)
bash run_workflow.sh --max-concurrent 20
# It automatically resumes from saved state in workflow.json

Workflow Overview

Architecture

MatterGen Structures
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 1: Pre-screening (prescreen.py + MatterSim) │
│ - SLURM job on compute node │
│ - Relax structures with MatterSim ML potential │
│ - Query MP for competing phases (cached per chemical system)│
│ - Compute energy_above_hull │
│ - Output: prescreening_stability.json │
│ - Filter: only E_hull < 0.1 eV/atom proceed to VASP │
└──────────────────────────────────────────────────────────────┘
↓
prescreening_stability.json
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 2: VASP Workflow (workflow_manager.py) │
│ - SLURM job on compute node │
│ - Initialize workflow database (JSON) │
│ - Batch submission loop: │
│ * Submit up to max_concurrent VASP jobs │
│ * Each structure: Relax → SC → PARCHG* → ELF (sequential)│
│ (* PARCHG only for semiconductors, band gap > 0.01 eV) │
│ * Monitor job completion every 60s │
│ * Submit new structures as slots free up │
└──────────────────────────────────────────────────────────────┘
↓
Analyze ELF + PARCHG Results (Bader analysis)
↓
Identify Electride Candidates

Job Chain Per Structure

  1. Pre-screening (MatterSim): Quick stability check → energy_above_hull
  2. Relax (VASP): Optimize geometry → CONTCAR
  3. SC (Self-Consistent): Accurate electronic structure → CHGCAR, WAVECAR, vasprun.xml
  4. PARCHG (all materials): Band-decomposed charge density → PARCHG-band0, PARCHG-band1, PARCHG-e0025, PARCHG-e05, PARCHG-e10
  5. ELF: Calculate electron localization → ELFCAR (PARCHG files copied here for analysis)

Directory Structure

/scratch/$USER/VASP_JOBS/
├── Li10B1N3/
│ ├── Li10B1N3_s001/
│ │ ├── Relax/
│ │ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ │ ├── job.sh
│ │ │ ├── CONTCAR (after completion)
│ │ │ ├── VASP_DONE (or VASP_FAILED)
│ │ │ └── vasp_*.out/err
│ │ └── SPE/ ← Unified SC-PARCHG-ELF directory
│ │ ├── job.sh ← Single SLURM job for all stages
│ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ ├── generate_parchg_incars.py ← Helper script (copied by workflow)
│ │ ├── SC_DONE, PARCHG_DONE ← Stage markers
│ │ ├── VASP_DONE (or VASP_FAILED) ← Final completion marker
│ │ ├── INCAR-SC, OSZICAR-SC, vasprun.xml-SC ← SC outputs
│ │ ├── INCAR-PARCHG-e0025, INCAR-PARCHG-e05, INCAR-PARCHG-e10
│ │ ├── INCAR-PARCHG-band0, INCAR-PARCHG-band1
│ │ ├── PARCHG.tar.gz ← Compressed PARCHG files
│ │ ├── INCAR-ELF
│ │ ├── ELFCAR ← ELF output
│ │ ├── ELF_DONE ← ELF stage marker
│ │ └── vasp_*.out/err
│ └── Li10B1N3_s002/
├── workflow.json # Job tracking database
├── prescreening_stability.json ← Pre-screening results
├── mp_mattersim.json ← Cached MP stable phases (MatterSim energies)
├── mp_vaspdft.json ← Cached MP stable phases (DFT energies)
└── electride_candidates.json # Analysis results

Workflow States

Each structure progresses through these states in workflow_manager.py:

PENDING (structure passed pre-screening, ready for VASP)
↓
RELAX_RUNNING → RELAX_DONE → SC_RUNNING → PARCHG_RUNNING → ELF_RUNNING → ELF_DONE
↓ ↓ ↓ ↓ ↓ ↓
RELAX_FAILED (skip) SC_FAILED PARCHG_FAILED ELF_FAILED (success)
Note: SC_RUNNING, PARCHG_RUNNING, and ELF_RUNNING are all part of one SPE job
State transitions happen automatically as stage markers are detected

Note: Pre-screening (MatterSim + MP hull analysis) is done separately by prescreen.py. Only structures that pass pre-screening (E_hull < threshold) are loaded into workflow_manager.py.

Key behaviors:

  • Only structures that passed pre-screening are processed
  • Reduced SLURM jobs: 2 jobs per structure (1 Relax + 1 SPE) instead of 8 jobs
  • SPE job runs sequentially: SC -> PARCHG (5 energy windows) -> ELF in one script
  • Stage markers: SC_DONE, PARCHG_DONE, VASP_DONE track progress within SPE job
  • State transitions: Workflow manager detects markers and transitions states automatically
  • PARCHG for ALL materials: Following HT-electride methodology
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied)
  • Workflow manager automatically submits next structure when slots free up
  • Failed jobs don't block other structures
  • Max concurrent limit applies to total running structures

SPE Workflow Architecture

The unified SPE (SC-PARCHG-ELF) workflow uses a clean separation of concerns:

Python (workflow_manager.py) handles:

  • INCAR/POSCAR/POTCAR/KPOINTS for Relax, SC, ELF jobs
  • Structure loading from CIF files and symmetrization
  • Database state tracking and job orchestration
  • Directory structure creation

Helper script (generate_parchg_incars.py) handles:

  • PARCHG INCAR generation (requires parsing vasprun.xml-SC)
  • Band index calculation from NELECT and SOC parameters
  • FFT grid extraction (NGXF, NGYF, NGZF)
  • Called from bash after SC completes

Bash (job.sh in SPE/) handles:

  • Sequential execution: SC → PARCHG (5 types) → ELF
  • File copying between stages (CHGCAR-SC, WAVECAR-SC reused)
  • PARCHG output renaming (PARCHG → PARCHG-e0025, etc.)
  • PARCHG compression (PARCHG-* → PARCHG.tar.gz) to save disk space
  • Cleanup between stages to prevent VASP issues
  • Stage marker creation (SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE)

Why this design:

  • PARCHG is the ONLY calculation requiring runtime VASP output parsing
  • Keeps Python code IDE-friendly (no embedded heredocs)
  • Helper script is testable standalone
  • Other INCARs are straightforward pymatgen calls (no external scripts needed)

Monitoring

Option 1: Workflow Status Tool (Recommended)

# Overall summary
python workflow_status.py ./VASP_JOBS/workflow.json

Shows:

  • Total structures
  • Status breakdown (PENDING, RELAX_RUNNING, SC_RUNNING, etc.)
  • Currently running count
  • Completion percentage

Additional views:

# Running jobs with SLURM job IDs
python workflow_status.py workflow.json --running
# Failed structures (for debugging)
python workflow_status.py workflow.json --failed
# Composition-level summary
python workflow_status.py workflow.json --compositions
# Recently completed structures
python workflow_status.py workflow.json --completed --limit 20
# Filter by specific state
python workflow_status.py workflow.json --details --state SC_RUNNING

Option 2: Reattach to Tmux

# See live workflow output
tmux attach -t vaspflow
# View, then detach: Ctrl+B, then D

Option 3: Check SLURM Queue

# Check running jobs
squeue -u $USER# Check job history
sacct -S $(date --date="7 days ago" -I) -u $USER# Detailed job info
scontrol show job <JOBID>

Option 4: Manual Inspection

# View database directly
cat ./VASP_JOBS/workflow.json | jq '.structures | to_entries | map({id: .key, state: .value.state})'# Check specific job directorycd ./VASP_JOBS/Li10B1N3/Li10B1N3_s001/Relax
ls -lh
tail vasp_*.out
tail OSZICAR

Analyzing Results for Electride Candidates

After ELF calculations complete, analyze structures for electride characteristics using Bader topological analysis on both ELFCAR and PARCHG files.

New in v2.0: Incremental analysis with MatterSim e_above_hull integration, PyXtal database storage, and stricter candidate filtering.

Step 1: Initial Analysis (All Structures)

Recommended: Run analysis as a SLURM job (not on login node):

# Submit analysis job with defaults
bash submit_analysis.sh
# Custom settings
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# View results when complete
cat electride_analysis.csv

Output:

  • electride_analysis.csv - All analyzed structures with interstitial volumes
  • electride_data.db - PyXtal database with all structures

Step 2: Filter High-Quality Candidates

Apply stricter volume thresholds to identify high-quality electride candidates:

# Filter with default thresholds (20 ų)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# Custom thresholds (stricter)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 25 \
--min-band 25

Filtering Criteria:

  • max(e0025, e05, e10) >= min-energy (default: 20 ų)
  • max(band0, band1) >= min-band (default: 20 ų)
  • Removes duplicate structures
  • Adds PyXtal symmetry information (space groups)

Output:

  • electride_candidates.db - Filtered high-quality candidates with symmetry
  • electride_candidates.csv - CSV table for quick viewing

Step 3: Extract CIF Files

Extract CIF files for the filtered candidates:

# Extract from filtered database
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Output: electride_CIF/*.cif - One CIF file per candidate

Step 4: Query Database

Use ase db to query and filter candidates:

# View all candidates
ase db electride_candidates.db
# Sort by space group (high symmetry first)
ase db electride_candidates.db \
formula,space_group_number,e_above_hull \
-s space_group_number-
# Filter by stability (< 50 meV/atom)
ase db electride_candidates.db 'e_above_hull<0.05'# Show interstitial volumes
ase db electride_candidates.db \
formula,e0025,e05,e10,band0,band1,e_above_hull
# Cubic structures (space group >= 195)
ase db electride_candidates.db 'space_group_number>=195'# High interstitial volume (e0025 > 50 ų)
ase db electride_candidates.db 'e0025>50'

What the Analysis Does

Initial Analysis (analyze.py):

  1. Reads ELFCAR - electron localization function from VASP SPE directory
  2. Extracts PARCHG files from PARCHG.tar.gz (5 types):
    • PARCHG-band0: Valence band maximum (VBM)
    • PARCHG-band1: Second highest occupied band (VBM-1)
    • PARCHG-e0025: Energy window [-0.025, 0.025] eV around Fermi level
    • PARCHG-e05: Energy window [-0.5, 0.025] eV
    • PARCHG-e10: Energy window [-1.0, 0.025] eV
  3. Runs Bader analysis on ELFCAR and each PARCHG file
  4. Filters interstitial electrons - sites far from atoms with high localization
  5. Reports volumes of interstitial electron density (ų) for each type
  6. Adds stability data - reads e_above_hull from prescreening_stability.json
  7. Extracts spacegroup - from CONTCAR using PyXtal (adaptive tolerance)
  8. Saves to database - stores all structures in electride_data.db

Filtering (filter_comb_db.py):

  1. Applies volume thresholds - only keeps structures with substantial interstitial volumes
  2. Symmetrizes structures - uses PyXtal with adaptive tolerance (coarse→fine)
  3. Removes duplicates - identifies and filters redundant structures
  4. Adds space group info - from PyXtal symmetry analysis
  5. Creates unified database - electride_candidates.db with structures + volumes
  6. Exports CSV - electride_candidates.csv for quick viewing

Key Features (v2.0)

Incremental Analysis:

  • Automatically skips already-analyzed structures from CSV and database
  • Run repeatedly as new ELF calculations complete without re-processing
  • Perfect for monitoring ongoing workflows

Enhanced Electride Criteria:

  • Old criteria: ANY of (e0025 > 0 OR e05 > 0 OR e10 > 0 OR band0 > 0)
  • New criteria: ALL of (e0025 > 0 AND e05 > 0 AND e10 > 0 AND band0 > 0)
  • More stringent to reduce false positives

DFT Integration:

  • Reads DFT energy_above_hull from compute_dft_e_hull.py output
  • Results sorted by stability (lowest e_above_hull first)
  • Most stable electride candidates rise to the top

PyXtal Database:

  • Saves all analyzed structures to electride_data.db
  • Adaptive symmetrization (tolerances: 1e-5 to 0.5)
  • P1 fallback ensures 100% save success
  • Query-able for advanced analysis

Analysis Parameters

analyze.py:

  • --threshold: Minimum ELF value for electride detection (default: 0.6)
  • --bader-exe: Path to Bader executable (default: bader in PATH)
  • --output: Output CSV file name (default: electride_analysis.csv)
  • --pyxtal-db: PyXtal database file (default: electride_data.db)
  • --prescreening: MatterSim stability JSON (default: ./VASP_JOBS/prescreening_stability.json)
  • --workers: Number of parallel workers (default: CPU count)

filter_comb_db.py:

  • --min-energy: Minimum for max(e0025, e05, e10) in ų (default: 20)
  • --min-band: Minimum for max(band0, band1) in ų (default: 20)
  • --output: Output database (default: electride_candidates.db)
  • --output-csv: Output CSV (default: electride_candidates.csv)

Understanding Results

Initial Analysis (electride_analysis.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045
Li10B1N4_s003,Li10B1N4,0.00,0.00,0.00,5.28,0.00,12,0.068

Columns:

  • formula: Structure ID
  • composition: Chemical formula
  • e0025, e05, e10: Interstitial volumes (ų) from energy windows
  • band0, band1: Interstitial volumes (ų) from band-specific charges
  • spacegroup: PyXtal space group (1 = P1 fallback)
  • e_above_hull: MatterSim energy above hull (eV/atom)

Electride Criteria:

  • (e0025 > 0 OR e05 > 0) AND (e10 > 0 OR band0 > 0)

Filtered Candidates (electride_candidates.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045

Additional Filtering:

  • max(e0025, e05, e10) >= 20 ų (substantial energy window volume)
  • max(band0, band1) >= 20 ų (substantial band-specific volume)
  • Duplicates removed
  • Space group from PyXtal symmetry analysis

Interpreting volumes (in ų):

  • > 20: High-quality electride (passes filtering)
  • 0-20: Weak electride (filtered out by default)
  • High across multiple columns: Strong, robust electride character

Example interpretation:

  • Li10B1N4_s001: High-quality electride (all volumes > 20 ų, stable)
  • Li10B1N4_s002: Moderate electride (volumes > 12 ų, borderline)
  • Li10B1N4_s003: Not electride (very low volumes)

Sorting:

  • Both CSVs sorted by e_above_hull (low → high)
  • Most thermodynamically stable candidates appear first

Console output during analysis:

Total ELF_DONE: 100
Semiconductors (with PARCHG): 15
Metals (ELFCAR only): 85
(All structures analyzed with PARCHG in SPE workflow)
Analyzing: Li10B1N4_s001 (VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE)
Spacegroup: 166
*** ELECTRIDE CANDIDATE *** (e0025=32.62, e05=31.82, e10=31.31, band0=35.11, band1=0.00)
Analyzing: Li10B1N4_s003 (VASP_JOBS/Li10B1N4/Li10B1N4_s003/SPE)
Spacegroup: 139
Not electride (e0025=0.00, e05=0.00, e10=0.00, band0=5.28, band1=0.00)

Filter output:

======================================================================
Filtering Electride Database with Stricter Criteria
======================================================================
Criteria:
max(e0025, e05, e10) >= 20.0 ų
max(band0, band1) >= 20.0 ų
Processing structures...
Added 100 structures...
Using P1 fallback for Ba8S7_s024
Added 200 structures...
Filtering Summary:
Input structures: 6134
Filtered out (below thresholds): 4512
Duplicates removed: 89
Failed to process: 0
Added to output database: 1533

Incremental Analysis Workflow

# Day 1: 50 ELF calculations done
bash submit_analysis.sh
# Output: 50 structures analyzed# → electride_analysis.csv (50 structures)# → electride_data.db (50 structures)# Filter to get high-quality candidates
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 25 high-quality)# electride_candidates.csv# Day 2: 30 more ELF calculations done (total 80)
bash submit_analysis.sh
# Output: Only 30 new analyzed (skips existing 50)# → electride_analysis.csv updated (80 total, re-sorted)# → electride_data.db updated (80 total)# Re-filter with updated data
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 40 high-quality)# Day 3: 20 more ELF calculations done (total 100)
bash submit_analysis.sh
# Output: Only 20 new analyzed# → Final electride_analysis.csv (100 structures)# Final filtering
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: Final electride_candidates.db (e.g., 50 high-quality)# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Benefits:

  • Incremental analysis saves time (only analyzes new structures)
  • Filtering is fast (~2 min) and can be adjusted without re-running Bader
  • Database is query-able at any stage

Direct Analysis (Advanced)

The analysis uses Electride.py internally via analyze.py. For manual testing:

# Test on single structure (SPE workflow)cd VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE
python3 ../../../../Electride.py . --bader-exe ~/apps/Bader/bader
# Run full analysis with all options
python3 analyze.py \
--db VASP_JOBS/workflow.json \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv \
--pyxtal-db electride_data.db \
--prescreening VASP_JOBS/prescreening_stability.json \
--workers 32
# Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20

Requirements:

  • ELFCAR file (generated by VASP with LELF=True in SPE/)
  • PARCHG.tar.gz (5 files compressed, automatically extracted during analysis)
  • Bader executable (download from: https://theory.cm.utexas.edu/henkelman/code/bader/)
  • (Optional) prescreening_stability.json for MatterSim e_above_hull values

Output Files

Initial Analysis:

  1. electride_analysis.csv: All analyzed structures with volumes
  2. electride_data.db: PyXtal database with all structures
  3. electride_analysis_detailed.log: Full console output

Filtered Candidates:

  1. electride_candidates.csv: High-quality candidates (CSV table)
  2. electride_candidates.db: PyXtal database with filtered structures + volumes
  3. electride_CIF/: Directory with CIF files for candidates

Performance

Analysis (analyze.py):

  • Incremental mode: Only analyzes new structures (minutes for 30 new structures)
  • Full analysis: ~5-10 minutes per structure (PARCHG extraction + Bader analysis)
  • Database saves: ~1 second per structure (with adaptive tolerance)
  • Parallel processing: Scales with CPU cores (32 cores recommended)

Filtering (filter_comb_db.py):

  • Time: ~2 minutes for 6000 structures
  • PyXtal symmetry: ~0.02 sec per structure (vs AFLOW: ~0.45 sec)
  • Speedup: 14× faster than AFLOW-based workflow
  • Duplicate removal: Automatic during processing

DFT Energy Above Hull Calculation

After VASP relaxations complete, compute DFT-level thermodynamic stability using your VASP energies combined with Materials Project DFT energies for competing phases.

Energy Method Comparison

Compare energies between different calculation methods to validate pre-screening accuracy and diagnose any systematic biases:

# Run comparison (requires dft_stability_results.json)
bash run_compare_energy_method.sh \
--vasp-jobs ./VASP_JOBS \
--outlier-threshold 0.5
# Monitor job
squeue -u $USER| grep compare_energy
tail -f compare_energy_method_*.out
# Results will be in: VASP_JOBS/energy_method_comparison.json# Plots: mp_phases_comparison_*.png, generated_structures_comparison_*.png

What it compares:

  1. MP On-Hull Phases: MatterSim energies vs MP raw DFT energies
  2. Generated Structures: MatterSim energies vs VASP-DFT energies

Important: The generated structures comparison now uses dft_stability_results.json as the single source of truth for VASP energies. This ensures exact consistency with hull_comparison plots (same structures, same outlier filtering).

Key metrics:

  • Pearson correlation between methods
  • Mean Absolute Error (MAE)
  • Systematic bias detection
  • Helps diagnose non-linear hull behavior

Usage

# Submit DFT hull calculation (after VASP relaxations complete)
bash run_dft_e_hull.sh \
--vasp-jobs ./VASP_JOBS \
--output dft_stability_results.json \
--prescreen-results ./VASP_JOBS/prescreening_stability.json
# Monitor job
squeue -u $USER| grep dft_e_hull
tail -f dft_e_hull_*.out
# Hull comparison (MatterSim vs DFT) is automatically generated# if --prescreen-results is provided to compute_dft_e_hull.py# Results will be in: VASP_JOBS/hull_comparison.json# Plots: hull_comparison_scatter.png, hull_comparison_residuals.png

What It Does

  1. Scans for completed VASP relaxations (RELAX_DONE or later states)
  2. Extracts VASP energies from vasprun.xml
  3. Queries MP for stable phases only (is_stable=True) - much faster than querying all phases
  4. Uses single cache file (mp_vaspdft.json) with automatic subsystem handling
  5. Computes DFT energy_above_hull for each structure using PDEntry
  6. Outputsdft_stability_results.json with decomposition products

Output Format

{
"summary": {
"total_structures": 100,
"processed_successfully": 95,
"failed": 5,
"energy_reference": "DFT uncorrected (VASP-PBE + MP stable phases only)",
"mp_phase_selection": "stable_only (is_stable=True)",
"mp_functional_filter": "mixed_pbe_pbeU"
},
"results": [
{
"structure_id": "Li10B1N4_s001",
"composition": "Li10B1N4",
"chemsys": "B-Li-N",
"vasp_energy_per_atom": -3.45678,
"dft_energy_above_hull": 0.023,
"decomposition_products": "Li3N (0.714) + BN (0.286)",
"num_mp_stable_phases": 18,
"error": null
}
]
}

Validation: MatterSim vs DFT Hull Comparison

The compute_dft_e_hull.py script automatically validates pre-screening accuracy by comparing MatterSim vs DFT hull values when --prescreen-results is provided:

Statistical metrics:

  • Pearson correlation (how well MatterSim predicts DFT)
  • Mean Absolute Error (MAE)
  • Root Mean Square Error (RMSE)

Pre-screening performance:

  • True Positives: Correctly passed (stable in both)
  • False Positives: Incorrectly passed (unstable in DFT, wasted VASP)
  • True Negatives: Correctly filtered (unstable in both)
  • False Negatives: Incorrectly filtered (stable in DFT, missed!)
  • Precision, Recall, F1 Score
  • Computational savings (% VASP avoided)

Output: hull_comparison.json with detailed analysis

When to Use

  • After some VASP relaxations complete: Validate pre-screening accuracy early
  • Before publication: Get accurate DFT stability data
  • To identify outliers: Find structures that were incorrectly filtered/passed

Performance

  • Time: ~1-2 hours for 100 structures (mostly MP API queries)
  • Resources: 8 CPUs, 32GB RAM (for large systems)
  • Caching: Uses MP IDs from pre-screening cache to minimize API calls

Troubleshooting

Workflow Manager Not Running

Symptom: Jobs complete but database still shows RUNNING state

Check if manager job is running:

squeue -u $USER| grep vaspflow_manager

Solution: Restart workflow manager if stopped

bash run_workflow.sh --max-concurrent 10
# It will detect completed jobs and update states

Jobs Not Progressing

Check:

# Check workflow manager job
squeue -u $USER| grep vaspflow_manager
tail -f workflow_manager_*.out
# See what's completed
find ./VASP_JOBS -name "VASP_DONE"| wc -l
find ./VASP_JOBS -name "VASP_FAILED"| wc -l
# Check VASP jobs in queue
squeue -u $USER# Check database state
python workflow_status.py ./VASP_JOBS/workflow.json

Fix: Restart workflow manager if it stopped

bash run_workflow.sh --max-concurrent 10

Failed Jobs

# List all failures
python workflow_status.py workflow.json --failed
# Investigate specific failurecd ./VASP_JOBS/Li10B1N3/Li10B1N3_s003/Relax
tail -50 vasp_*.err
tail -50 OSZICAR
grep -i "error\|killed\|fail" vasp_*.out

Common failure causes:

  • Walltime limit hit (24 hours default)
  • Convergence issues (check OSZICAR)
  • Memory issues (check vasp_*.err)
  • POTCAR problems (check first few lines of vasp_*.out)

Resetting Failed Jobs for Retry

Use reset_failed_jobs.py to reset failed structures and retry them:

# Step 1: List all failed structures to understand what went wrong
python3 reset_failed_jobs.py --list
# Output shows failures grouped by stage:# RELAX_FAILED: 72 structures# SC_FAILED: 4 structures# PARCHG_FAILED: 4 structures# Step 2: Dry run to preview changes (recommended)
python3 reset_failed_jobs.py --dry-run --clean
# Step 3: Reset all failed jobs
python3 reset_failed_jobs.py --clean
# OR reset specific stage only
python3 reset_failed_jobs.py --stage RELAX --clean
python3 reset_failed_jobs.py --stage SC --clean
python3 reset_failed_jobs.py --stage PARCHG --clean
# Step 4: Resume workflow to retry
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10

What it does:

  • RELAX_FAILEDPENDING (retry from scratch)
  • SC_FAILEDRELAX_DONE (retry SC using existing relaxed structure)
  • PARCHG_FAILEDSC_DONE (retry PARCHG using existing SC results)
  • --clean flag removes VASP_FAILED markers for clean restart
  • Creates automatic backup: workflow.json.bak

Important: Investigate failure causes before blindly retrying. Some structures may have fundamental issues (bad geometry, unconverged, etc.) and will fail repeatedly.

POTCAR Not Found

# Check environmentecho$PMG_VASP_PSP_DIR# Verify structure
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
# Set if neededexport PMG_VASP_PSP_DIR=$HOME/apps/PBE64
# Add to ~/.bashrc to persist

Workflow Manager Job Issues

# Check if manager job is running
squeue -u $USER| grep vaspflow_manager
# View manager log
tail -100 workflow_manager_*.out
# Cancel stuck manager job
scancel <JOBID># Restart (database persists!)
bash run_workflow.sh --max-concurrent 10

Jobs Stuck in SLURM Queue

# Check job status
squeue -u $USER -o "%.18i %.9P %.30j %.8T %.10M %.6D %R"# Check why pending
squeue -u $USER -j <JOBID> --start
# Cancel stuck job if needed
scancel <JOBID># Workflow will mark it as failed on next check

Database Corruption

# Backup database
cp workflow.json workflow.json.backup
# Reinitialize (keeps existing directories)
python workflow_manager.py --init-only \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS
# Manually merge completed jobs from backup if needed

Parallel Pre-screening Results Missing

Symptom: After running submit_parallel_prescreen.sh, the prescreening_stability.json file is empty or only contains results from one batch.

Cause: Multiple parallel jobs writing to the same file cause race conditions and data loss.

Solution:

  1. Each batch processes a different subset of compositions using --start-composition (batch 0: comps 0-399, batch 1: 400-799, etc.)
  2. Each batch writes to its own file (prescreening_stability_batch0.json, etc.)
  3. After all jobs complete, merge them with merge_prescreen_batches.py:
# Check that all batch jobs completed
squeue -u $USER| grep prescreen # Should be empty# List batch result files
ls ./VASP_JOBS/prescreening_stability_batch*.json
ls ./VASP_JOBS/prescreening_structures_batch*.db
ls ./VASP_JOBS/mp_mattersim.json # Shared cache (not batch-specific)# Merge all batch results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# OR skip database merge (faster, JSON only)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS --skip-database
# Verify merged results
cat ./VASP_JOBS/prescreening_stability.json | jq '.metadata.total_structures'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Check shared MP cache
ls -lh ./VASP_JOBS/prescreening_structures.db # Check database exists

Prevention: Always run merge_prescreen_batches.py after parallel prescreening jobs complete.


Configuration

Key Parameters

Pre-screening (prescreen.py):

# Single GPU job
python prescreen.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0 \ # Max structures per composition
--batch-size 32 \ # Structures per batch (calculator reuse)
--mp-api-key YOUR_KEY \ # Materials Project API key
--hull-threshold 0.05 \ # E_hull threshold (eV/atom)
--device cuda \ # MatterSim device: cpu or cuda
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Automatically splits compositions across GPU nodes

VASP Workflow (workflow_manager.py):

python workflow_manager.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \ # Max structures running simultaneously
--max-compositions 20 \ # Limit number of compositions (optional)
--max-structures 0 \ # Max structures per composition
--check-interval 60 # Status check interval (seconds)

Recommendations:

  • Pre-screening:
    • --batch-size: 32 for A40/A100 GPUs (48GB VRAM), reduce to 16 for smaller GPUs
    • --hull-threshold: 0.1 eV/atom filters most unstable structures, use 0.05 for stricter filtering
    • --device: Use cuda for GPU acceleration (5-10× faster than CPU)
    • --mp-api-key: Get your free API key at https://next-gen.materialsproject.org/api
    • --pure-pbe: OPTIONAL flag to exclude PBE+U (recommended to OMIT for best accuracy)
      • Default (no flag): Mixed PBE/PBE+U (matches MP phase diagram methodology)
      • With flag: Pure GGA-PBE only (may reduce accuracy for transition metal systems)
    • MP API: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • Large datasets: Use submit_parallel_prescreen.sh to split across multiple GPUs
    • GPU memory: Set export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True in SLURM script
  • VASP Workflow:
  • --max-concurrent: 10-20 for typical HPC cluster
  • --check-interval: 60s is good balance
  • --max-compositions: Omit to process all
    • PyXtal: Structures automatically symmetrized for better convergence

SLURM Settings

Edit create_slurm_script() in workflow_manager.py (lines 163-176):

script=f"""#!/bin/bash#SBATCH --partition=Apus # Change partition#SBATCH --ntasks=32 # Change cores#SBATCH --time=1-00:00:00 # Change walltime (1 day)#SBATCH --mem=64G # Change memoery#SBATCH --output={job_dir}/vasp_%j.out#SBATCH --error={job_dir}/vasp_%j.err

VASP Input Settings

Edit create_vasp_inputs() in workflow_manager.py (lines 129-161):

Relax (line 135-142):

vis=MPRelaxSet(structure, user_incar_settings={
'EDIFF': 1e-6, # Energy convergence'EDIFFG': -0.01, # Force convergence (eV/Å)'NSW': 200, # Max ionic steps'PREC': 'Accurate',
'ISMEAR': 0, # Gaussian smearing'SIGMA': 0.05,
})

SC/Static (line 143-148):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LAECHG': True, # Write core charge'LCHARG': True, # Write CHGCAR
})

ELF (line 149-156):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LELF': True, # Calculate ELF'ADDGRID': True, # Finer FFT grid'NSW': 0, # No ionic steps'IBRION': -1,
})

Electride Detection Parameters

python analyze_completed.py \
--threshold 0.6 \ # ELF threshold (0.5-0.7 typical)
--min-distance 1.5 \ # Min distance from atoms (Å)
--volume-threshold 0.5 # Min interstitial volume (ų)

Performance

Per Structure (typical, 32 cores)

Pre-screening (MatterSim):

  • Relaxation: 10-30s per structure (CPU) or 5-10s (GPU)
  • MP query: One-time per chemical system (~2-5 min, cached)
  • Hull analysis: <1s per structure

VASP calculations:

  • Relax: 2-6 hours
  • SPE job (SC + PARCHG + ELF sequential): 5-10 hours
    • SC: 1-3 hours
    • PARCHG (5 sequential): 2.5-5 hours (5 × 30-60 min)
    • ELF: 1-2 hours
  • Total VASP time: 7-16 hours/structure
  • SLURM overhead: Reduced by 75% (2 jobs instead of 8 jobs per structure)

With pre-screening (filters ~60% structures):

  • Effective time: 3-6 hours/structure (accounting for filtered structures)
  • Savings: 40-60% of total VASP computation time

Example Workflow (100 structures, max_concurrent=10, with pre-screening)

TimeActionRunningCompletedNotes
T=0Pre-screen 100 structures00MatterSim + MP
T=1hPre-screening done0060 pass, 40 filtered out
T=1hSubmit first 10 Relax jobs100Only stable structures
T=5h10 Relax done, submit 10 SPE100SPE = SC+PARCHG+ELF
T=13h10 SPE done, submit new1010~8h per SPE job
...Repeat10...
T=53hAll 60 complete06040 filtered by pre-screening

Wall time: ~53 hours for 100 structures (60 pass pre-screening)
Core-hours: ~24,000 (60 structures × 12.5h avg × 32 cores / 2 efficiency)
SLURM jobs: 120 total (vs 480 with old workflow)
Savings: 40-60% computational time from pre-screening, 75% fewer SLURM jobs


MatterSim Pre-screening

Pre-screening uses the MatterSim ML potential to quickly evaluate thermodynamic stability before running expensive VASP calculations. This is done in a separate step using prescreen.py, which generates prescreening_stability.json with structures that pass the stability threshold.

How It Works

  1. MatterSim Relaxation: Structures relaxed in batches with calculator reuse for GPU memory efficiency
  2. MP Reference Phases Query: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • The modern mp_api.client misses many stable GGA phases needed for accurate hull calculations
    • Strict filtering: only accepts entries with -GGA or -GGA+U suffix in entry_id
    • Uses uncorrected_energy (raw DFT, no MP corrections) to match MatterSim energies
    • Optional --pure-pbe flag to exclude PBE+U (use pure GGA-PBE only)
  3. Re-relax MP Structures: MP GGA structures are re-relaxed with MatterSim for consistent energy reference
  4. Convex Hull: Build phase diagram using MatterSim energies with PDEntry
  5. Output: Generate prescreening_stability.json with structures that pass threshold
  6. VASP Workflow Filter: workflow_manager.py reads prescreening_stability.json and only processes structures with E_hull < threshold (default: 0.1 eV/atom)

Key Optimizations (NEW)

Batch Processing:

  • MatterSimCalculator reused across 32 structures per batch (configurable with --batch-size)
  • Dramatically reduces GPU memory overhead and initialization time
  • Automatic GPU memory cleanup between batches
  • Supports CUDA memory expansion: PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

Complete GGA Coverage with Legacy API:

  • Uses legacy pymatgen.ext.matproj.MPRester instead of modern mp_api.client
  • Modern API misses many stable GGA phases critical for accurate hull calculations
  • Queries ALL GGA/GGA+U entries via get_entries_in_chemsys()
  • Strict suffix filtering: Only accepts entries with -GGA or -GGA+U suffix in entry_id
  • Excludes r2SCAN, SCAN, and entries without explicit functional suffix
  • Uses uncorrected_energy (raw DFT, no MP anion/composition corrections)
  • Optional --pure-pbe flag to exclude PBE+U (for pure GGA-PBE calculations only)
  • More accurate phase diagrams with comprehensive GGA reference phases

Single Global Cache Files:

  • mp_mattersim.json: All MatterSim-relaxed MP phases with chemsys field
  • mp_vaspdft.json: All MP DFT energies with chemsys field
  • Automatically handles overlapping chemical systems (e.g., B-Li-N includes B, Li, N subsystems)
  • No more separate cache directories with duplicate data

Parallel Multi-GPU Processing:

  • submit_parallel_prescreen.sh: Splits compositions across multiple GPU nodes
  • Each batch job writes to unique files:
    • JSON: prescreening_stability_batch0.json, prescreening_stability_batch1.json, ...
    • Database: prescreening_structures_batch0.db, prescreening_structures_batch1.db, ...
  • MP cache is SHARED across all batches using dual-level file locking:
    • Single file: mp_mattersim.json (all batches read/write safely)
    • Cache I/O locking: mp_mattersim.lock prevents file corruption
    • Per-chemsys locking: mp_cache_{chemsys}.lock prevents duplicate MP queries
    • When Batch 0 queries Ba-O, other batches wait for it to finish
    • After Batch 0 completes, other batches read from cache (no duplicate API calls)
    • Lock files auto-cleaned after merge
  • After all jobs complete, run merge_prescreen_batches.py to combine results
  • Command-line configurable (use --help for full options)
  • Configurable compositions per job (default: 400)
  • Linear speedup with number of GPUs
  • Example: 2000 compositions → 5 GPU nodes = 5x faster
  • Critical: File locking ensures safe concurrent access to shared MP cache

PyXtal Symmetrization:

  • Structures automatically symmetrized before MatterSim relaxation
  • Same symmetrization applied to VASP initial structures in workflow_manager.py
  • Improves convergence and consistency between pre-screening and VASP

Configuration

# Option A: Single GPU job (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--device cuda \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Pure GGA-PBE only (omit for best accuracy)# View all options
bash submit_parallel_prescreen.sh --help
# Monitor parallel jobs
squeue -u $USER| grep prescreen
# After all parallel jobs complete, merge batch results
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# This combines:# - prescreening_stability_batch*.json → prescreening_stability.json# - prescreening_structures_batch*.db → prescreening_structures.db# - mp_mattersim.json is already shared (no merging needed)# Options:# --keep-batches: preserve individual batch files (default: delete after merge)# --skip-database: skip database merge, only merge JSON (faster)# Custom options for single GPU
bash run_prescreen.sh \
--batch-size 64 \ # Larger batch (requires more GPU memory)
--hull-threshold 0.05 \ # Stricter threshold (fewer pass)
--device cuda # Use GPU (much faster than CPU)# Check results and cache
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Number of cached MP phases
cat ./VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'# By chemical system# Step 2: Run VASP workflow (automatically filters based on pre-screening)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Note: VASP structures are automatically symmetrized with PyXtal before relaxation# This ensures consistency with pre-screening and improves convergence# By default, workflow_manager.py looks for:# ./VASP_JOBS/prescreening_stability.json## To use a different file:
bash run_workflow.sh --prescreen-results /path/to/custom_results.json
# To skip filtering (process all structures):# (Not recommended - remove prescreening_stability.json first)
bash run_workflow.sh # Will warn if file not found

Performance Impact

Overhead (with optimizations):

  • Single GPU: ~30-60 minutes for 100 structures across 10 chemical systems
  • Parallel (5 GPUs): ~10-15 minutes for same dataset (5x speedup)
  • Batch processing: 3-5x faster than previous per-structure calculator creation
  • Stable phases only: 10-20x faster MP queries (20-50 phases vs 500+ phases)
  • First structure in each chemical system takes longer (MP query + cache)
  • Subsequent structures in same system benefit from shared cache

Cache Efficiency:

  • Single mp_mattersim.json file (~1-5 MB) replaces multiple per-chemsys files
  • Automatic deduplication of overlapping subsystems
  • B-Li-N system includes: B, Li, N, B-Li, B-N, Li-N, B-Li-N (7 subsystems in 1 cache)

Savings:

  • Filters 50-80% of structures (typical)
  • Saves 4-10 VASP hours per filtered structure
  • Net savings: 40-60% of total computation time
  • Additional: Pre-screening itself is 3-5x faster with batch processing

Checking Pre-screening Results

# View pre-screening summary
cat VASP_JOBS/prescreening_stability.json | jq '.summary'# View individual results
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | { id: .structure_id, chemsys: .chemsys, E_hull: .energy_above_hull, passed: .passed_prescreening}'| less
# Count passed vs filtered
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==true)'| jq -s 'length'
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==false)'| jq -s 'length'

Pre-screening Utilities

Visualizing Energy Distribution

Use plot_e_above_hull.py to visualize the energy distribution and verify your threshold:

# Plot histogram of energy_above_hull values
python3 plot_e_above_hull.py \
--input ./VASP_JOBS/prescreening_stability.json \
--output histogram.png \
--bins 100 \
--max-energy 2.0

Extracting Stable Structures

Use extract_stable_structs.py to extract CIF files for structures that passed pre-screening:

# Extract CIF files for structures that passed pre-screening
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

Troubleshooting

All structures filtered out:

  • Threshold may be too strict (try --hull-threshold 0.2)
  • Check if MP API key is working
  • Verify MatterSim is installed correctly

Pre-screening taking too long:

  • Use GPU: --device cuda
  • MP cache should build once per chemical system
  • Check MP API rate limits (built-in backoff)

SLURM Job Management Reference

Basic SLURM Commands

ActionCommand
Submit workflow managerbash run_workflow.sh --max-concurrent 20
Check job queuesqueue -u $USER
Check specific jobsqueue -j <JOBID>
View job logtail -f workflow_manager_<JOBID>.out
Cancel jobscancel <JOBID>
Job historysacct -u $USER
Job detailsscontrol show job <JOBID>

Typical Usage Pattern

# Day 1: Start workflow
ssh your_cluster
cd /scratch/$USER/vaspflow
bash run_workflow.sh --max-concurrent 20
# Note the job ID, then log out# Day 2: Check progress (from anywhere)
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if manager is still running
squeue -u $USER| grep vaspflow_manager
# Check workflow progress
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# View manager log
tail -f workflow_manager_*.out

Files

FilePurpose
prescreen.pyMatterSim pre-screening with batch processing
run_prescreen.shSubmit single-GPU pre-screening wrapper
submit_prescreen.shSLURM script for single-GPU pre-screening
submit_parallel_prescreen.shNEW: Parallel multi-GPU prescreening across nodes
merge_prescreen_batches.pyNEW: Merge parallel batch results into single file
plot_e_above_hull.pyVisualize pre-screening energy distribution
extract_stable_structs.pyExtract CIF files for stable structures
workflow_manager.pyVASP workflow with PyXtal symmetrization
run_workflow.shSubmit workflow wrapper (user-facing)
submit_workflow_manager.shSLURM script for workflow manager
workflow_status.pyStatus checking and reporting
reset_failed_jobs.pyReset failed jobs to retry (RELAX/SC/PARCHG)
compute_dft_e_hull.pyCompute DFT energy_above_hull + MatterSim comparison
run_dft_e_hull.shSubmit DFT hull wrapper (user-facing)
submit_dft_e_hull.shSLURM script for DFT hull calculation
compare_energy_methods.pyCompare MatterSim vs DFT energies (uses dft_stability_results.json)
run_compare_energy_method.shSubmit energy method comparison wrapper
submit_compare_energy_method.shSLURM script for energy method comparison
analyze.pyOrchestrates electride analysis (calls Electride.py)
analyze.shSLURM script for analysis job
Electride.pyBader analysis on ELFCAR + PARCHG files
submit_analysis.shSubmit analysis wrapper (user-facing)
filter_comb_db.pyNEW: Filter candidates with stricter volume criteria + PyXtal symmetry
extract_electride_struct.pyExtract CIF files from filtered database
generate_parchg_incars.pyHelper script to generate PARCHG INCARs from vasprun.xml-SC

Key Features:

  • Unified SPE workflow: SC-PARCHG-ELF run sequentially in one SLURM job (2 jobs per structure vs 8)
  • Simplified directory structure: Relax/ and SPE/ subdirectories (vs 7+ subdirectories)
  • Stage markers: SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE track progress within SPE job
  • Reduced SLURM overhead: 75% fewer jobs submitted to queue
  • Clean code separation: Python for VASP inputs, bash for workflow orchestration
  • Helper script for PARCHG: Standalone script generates PARCHG INCARs (band indices from vasprun.xml-SC)
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied during relaxation)
  • Batch processing: prescreen.py reuses MatterSimCalculator across structures (3-5× faster)
  • Parallel prescreening: submit_parallel_prescreen.sh splits across GPU nodes (linear speedup)
  • Complete GGA coverage: Uses legacy pymatgen.ext.matproj.MPRester for comprehensive GGA/GGA+U phases
  • Strict functional filtering: Only accepts entries with -GGA or -GGA+U suffix (excludes r2SCAN/SCAN)
  • Uncorrected energies: Uses raw DFT energies (no MP corrections) for accurate hull calculations
  • Optional pure-pbe: --pure-pbe flag to filter MP entries to pure GGA-PBE only (exclude PBE+U)
  • Single cache files: mp_mattersim.json and mp_vaspdft.json in VASP_JOBS/ directory
  • PyXtal symmetrization: Automatic structure symmetrization in both prescreening and VASP workflow
  • Two-step electride filtering: Initial analysis saves all data, stricter filtering for high-quality candidates
  • Fast symmetry analysis: PyXtal-based filtering (14× faster than AFLOW)
  • Query-able database: ase db commands for filtering candidates by stability, symmetry, or volumes
  • PDEntry for hulls: Uses PDEntry instead of ComputedEntry for accurate phase diagram analysis
  • reset_failed_jobs.py resets failed VASP jobs to retry them without data loss
  • Integrated hull validation: compute_dft_e_hull.py automatically validates pre-screening accuracy with plots and statistics
  • Energy method comparison: compare_energy_methods.py uses dft_stability_results.json as single source of truth for exact consistency
  • User-friendly wrapper scripts provide consistent interface across all stages

Best Practices

  1. Run pre-screening first with prescreen.py to save 40-60% of VASP computation
  2. Use parallel prescreening (submit_parallel_prescreen.sh) for large datasets (>500 compositions)
  3. Merge batch results with merge_prescreen_batches.py after all parallel jobs complete
  4. Optimize batch size based on GPU memory: 32 for A40/A100 (48GB), 16 for smaller GPUs
  5. Wait for pre-screening to complete before starting VASP workflow
  6. Check pre-screening results (prescreening_stability.json) to verify threshold is appropriate
  7. Inspect cache files (mp_mattersim.json, mp_vaspdft.json) to verify MP data quality
  8. Submit both jobs as SLURM jobs (required on most HPC systems)
  9. Monitor from login node using workflow_status.py instead of viewing logs constantly
  10. Set reasonable max_concurrent (10-20) to avoid queue congestion
  11. Monitor your quota on /scratch periodically (cache files are now much smaller: ~1-5 MB total)
  12. Check failed jobs early to catch systematic issues
  13. Start small (test with 2-3 structures first using --max-compositions 2 --max-structures 2)
  14. Trust PyXtal symmetrization - structures are automatically symmetrized for consistency

Common Workflows

Production Run (Full Scale)

# Step 1: Pre-screening# Option A: Single GPU (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--device cuda \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets >500 compositions)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400
# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Auto-splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor with: squeue -u $USER | grep prescreen# Wait for completion, check and visualize results
cat VASP_JOBS/prescreening_stability.json | jq '.summary'
cat VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'
jq '.results[] | select(.passed_prescreening == true) | {structure_id, energy_above_hull}' VASP_JOBS/prescreening_stability.json
python3 plot_e_above_hull.py --bins 100
# (Optional) Extract stable structures for inspection
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# Step 2: VASP workflow (structures automatically symmetrized with PyXtal)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0 \
--check-interval 120
# Step 3: Analyze electride candidates
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# Step 4: Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# Step 5: Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Step 6: Query and explore
ase db electride_candidates.db
ase db electride_candidates.db 'e_above_hull<0.05' -s space_group_number-

Resume After Interruption

# Check if still running
squeue -u $USER| grep vaspflow_manager
# If stopped, restart - database persists
bash run_workflow.sh --max-concurrent 20

Integration with MatterGen

# 1. Generate structures with MatterGencd~/mattergen_test/ternary_electride
bash generate_ternary_csp.sh
# 2. Transfer to HPC scratchcd /scratch/$USER
cp -r ~/mattergen_test/results/ternary_csp_electrides mattergen_results/
# 3. Run pre-screening (as SLURM job)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Wait for pre-screening to complete
squeue -u $USER| grep prescreen
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 3b. Visualize and extract stable structures (optional)
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 4. Start VASP workflow (as SLURM job)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20
# 5. Monitor and analyze
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# 6. Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# 7. Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# 8. Query candidates
ase db electride_candidates.db 'e_above_hull<0.05'

Credits & References

Credits:

Tools & Libraries:

Key Paper:

@article{zhuComputationalDiscoveryInorganic2019,
title = {Computational {{Discovery}} of {{Inorganic Electrides}} from an {{Automated Screening}}},
author = {Zhu, Qiang and Frolov, Timofey and Choudhary, Kamal},
year = 2019,
month = nov,
journal = {Matter},
volume = {1},
number = {5},
pages = {1293--1303},
issn = {2590-2385},
doi = {10.1016/j.matt.2019.06.017},
}
@misc{tao2026acceleratedinorganicelectridesdiscovery,
title={Accelerated Inorganic Electrides Discovery by Generative Models and Hierarchical Screening}, author={Shuo Tao and Qiang Zhu},
year={2026},
eprint={2601.21077},
archivePrefix={arXiv},
primaryClass={cond-mat.mtrl-sci},
url={https://arxiv.org/abs/2601.21077}, }

About

DFT-HT Workflow for screening inorganic electrides

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ElectrideFlow - High-Throughput Inorganic Electride Discovery Workflow Accelerated by Generative Models and Hierarchical Prescreening

A four-stage intelligent workflow for high-throughput inorganic electride discovery on HPC clusters:

  1. Chemical Exploration - Generative AI models (MatterGen) explore composition space targeting electride-favorable chemistries
  2. Stability Screening - MatterSim (MLP) pre-screening filters structures by energy above hull before expensive DFT calculations
  3. Electride Identification - Coarse DFT relaxation with ELF & PARCHG topological analysis to identify electride candidates
  4. Refinement - Tight DFT relaxation with refined convex hull analysis for final candidate validation

Table of Contents


Features

MatterSim pre-screening - filter structures by energy_above_hull before VASP (saves 40-60% computation)
Batch processing - reuses MatterSimCalculator across structures for GPU memory efficiency
Parallel prescreening - split prescreening across multiple GPU nodes for faster throughput
Stable phases only - queries only on-hull MP phases for accurate, fast convex hull analysis
Smart caching - single global cache files (mp_mattersim.json, mp_vaspdft.json) handle overlapping systems
PyXtal symmetrization - automatic structure symmetrization for better VASP convergence
Unified SPE workflow - SC-PARCHG-ELF in single job (75% fewer SLURM jobs)
Batch submission - submit n structures at a time, auto-submit more as jobs complete
Dynamic monitoring - check status and submit new jobs automatically
Local JSON database - no network dependencies, works on HPC
Smart workflow - Pre-screen → Relax → SPE (SC + PARCHG + ELF sequential)
PARCHG analysis - band-edge charge density for accurate electride identification
Two-step filtering - initial analysis saves all, stricter filtering for candidates
Fast symmetry - PyXtal-based (14× faster than AFLOW)
Query-able database - ase db commands for candidate exploration
Pymatgen input generation - INCAR, POSCAR, POTCAR, KPOINTS
Bader analysis - identify electride candidates with topological analysis
Interrupt-safe - resume from any interruption
HPC-friendly - workflow manager runs as SLURM job


Quick Start

1. Setup Environment

# On HPC login nodecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# Copy files from your local machine:# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow orchestration# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Monitor workflow progress# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# Load CUDA runtime (check your HPC's available versions, need >= 11.8)
module load cuda/11.8
# Create conda environment
conda create -n mattersim python=3.10
conda activate mattersim
# Install PyTorch with matching CUDA version FIRST# (adjust cu118 to match your loaded CUDA module)
pip install torch==2.5.1+cu118 torchvision==0.20.1+cu118 torchaudio==2.5.1+cu118 \
--index-url https://download.pytorch.org/whl/cu118
pip install torch_scatter==2.1.2+pt25cu118 torch_sparse==0.6.18+pt25cu118 \
torch_cluster==1.6.3+pt25cu118 torch_spline_conv==1.2.2+pt25cu118 \
-f https://data.pyg.org/whl/torch-2.5.1+cu118.html
pip install torch-geometric==2.7.0 pytorch-lightning==2.0.6
# Install pymatgen/mp-api (pinned versions for MP API compatibility)
pip install pymatgen==2024.10.29 mp-api==0.43.0 monty==2024.7.30 emmet-core==0.84.10
# Install other dependencies
pip install numpy>=2.0 ase==3.23.0 pyxtal==1.1.1
# Install MatterSim last (--no-deps to avoid overriding torch versions)
pip install mattersim --no-deps
# Then install any missing mattersim deps that don't conflict:
pip install torch-ema torch-runstats torchmetrics
# Set environment variables in ~/.bashrcecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc

2. Pre-screening with MatterSim (NEW Step)

# Option A: Single GPU job (for small datasets)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--device cuda \
--compositions-per-job 400
# Optional: Add --pure-pbe flag to filter MP entries to pure GGA-PBE only# (default is mixed PBE/PBE+U which is recommended for best accuracy)# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Automatically splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# When done, check results
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# View cache files (single global files with chemsys field)
ls -lh ./VASP_JOBS/mp_mattersim.json
cat ./VASP_JOBS/mp_mattersim.json | jq '.[0]'# (Optional) Visualize results and extract CIF files
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

3. VASP Workflow (Run After Pre-screening)

# Submit VASP workflow manager (processes structures that passed pre-screening)cd /scratch/$USER/vaspflow
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Check job status
squeue -u $USER
tail -f workflow_manager_<JOBID>.out

4. Monitor Progress

cd /scratch/$USER/vaspflow
conda activate mattersim
# Check workflow manager job
squeue -u $USER# View workflow manager log
tail -f workflow_manager_<JOBID>.out
# Overall workflow status
python workflow_status.py ./VASP_JOBS/workflow.json
# Composition breakdown
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# Running VASP jobs
python workflow_status.py ./VASP_JOBS/workflow.json --running
# Failed structures
python workflow_status.py ./VASP_JOBS/workflow.json --failed

5. Analyze Results

# Submit electride analysis as SLURM job
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# When complete, view all analyzed structures
cat electride_analysis.csv
# Filter with stricter criteria to get high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# View filtered candidates
cat electride_candidates.csv
# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Query database for specific criteria
ase db electride_candidates.db 'e_above_hull<0.05'

Complete Setup Guide

Initial Setup (One-time)

# 1. SSH to HPC
ssh your_cluster
# 2. Create conda environment with all dependencies
conda create -n mattersim python=3.10
conda activate mattersim
conda install -c conda-forge pymatgen mp-api
pip install mattersim ase
# 3. Setup workspacecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# 4. Upload workflow scripts from your local machine# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Status monitoring# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# 5. Make scripts executable
chmod +x *.py *.sh
# 6. Set environment variablesecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc
# 7. Verify setup
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
echo"MP API Key: $MP_API_KEY"

Starting a Workflow

# 1. SSH to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# 2. Run pre-screening first (MatterSim + MP)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# Wait for pre-screening to complete (~1-2 hours for 100 structures)# Check results:
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 2b. (Optional) Visualize and extract stable structures
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 3. Submit VASP workflow manager (processes passing structures)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20 \
--max-structures 0
# 4. Monitor (optional)
squeue -u $USER# Check job status
tail -f workflow_manager_*.out # View log# You can now safely log out - workflow runs as SLURM job!

Resuming After Interruption

# SSH back to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if workflow manager is still running
squeue -u $USER| grep vaspflow_manager
# If not running, resubmit (database persists!)
bash run_workflow.sh --max-concurrent 20
# It automatically resumes from saved state in workflow.json

Workflow Overview

Architecture

MatterGen Structures
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 1: Pre-screening (prescreen.py + MatterSim) │
│ - SLURM job on compute node │
│ - Relax structures with MatterSim ML potential │
│ - Query MP for competing phases (cached per chemical system)│
│ - Compute energy_above_hull │
│ - Output: prescreening_stability.json │
│ - Filter: only E_hull < 0.1 eV/atom proceed to VASP │
└──────────────────────────────────────────────────────────────┘
↓
prescreening_stability.json
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 2: VASP Workflow (workflow_manager.py) │
│ - SLURM job on compute node │
│ - Initialize workflow database (JSON) │
│ - Batch submission loop: │
│ * Submit up to max_concurrent VASP jobs │
│ * Each structure: Relax → SC → PARCHG* → ELF (sequential)│
│ (* PARCHG only for semiconductors, band gap > 0.01 eV) │
│ * Monitor job completion every 60s │
│ * Submit new structures as slots free up │
└──────────────────────────────────────────────────────────────┘
↓
Analyze ELF + PARCHG Results (Bader analysis)
↓
Identify Electride Candidates

Job Chain Per Structure

  1. Pre-screening (MatterSim): Quick stability check → energy_above_hull
  2. Relax (VASP): Optimize geometry → CONTCAR
  3. SC (Self-Consistent): Accurate electronic structure → CHGCAR, WAVECAR, vasprun.xml
  4. PARCHG (all materials): Band-decomposed charge density → PARCHG-band0, PARCHG-band1, PARCHG-e0025, PARCHG-e05, PARCHG-e10
  5. ELF: Calculate electron localization → ELFCAR (PARCHG files copied here for analysis)

Directory Structure

/scratch/$USER/VASP_JOBS/
├── Li10B1N3/
│ ├── Li10B1N3_s001/
│ │ ├── Relax/
│ │ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ │ ├── job.sh
│ │ │ ├── CONTCAR (after completion)
│ │ │ ├── VASP_DONE (or VASP_FAILED)
│ │ │ └── vasp_*.out/err
│ │ └── SPE/ ← Unified SC-PARCHG-ELF directory
│ │ ├── job.sh ← Single SLURM job for all stages
│ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ ├── generate_parchg_incars.py ← Helper script (copied by workflow)
│ │ ├── SC_DONE, PARCHG_DONE ← Stage markers
│ │ ├── VASP_DONE (or VASP_FAILED) ← Final completion marker
│ │ ├── INCAR-SC, OSZICAR-SC, vasprun.xml-SC ← SC outputs
│ │ ├── INCAR-PARCHG-e0025, INCAR-PARCHG-e05, INCAR-PARCHG-e10
│ │ ├── INCAR-PARCHG-band0, INCAR-PARCHG-band1
│ │ ├── PARCHG.tar.gz ← Compressed PARCHG files
│ │ ├── INCAR-ELF
│ │ ├── ELFCAR ← ELF output
│ │ ├── ELF_DONE ← ELF stage marker
│ │ └── vasp_*.out/err
│ └── Li10B1N3_s002/
├── workflow.json # Job tracking database
├── prescreening_stability.json ← Pre-screening results
├── mp_mattersim.json ← Cached MP stable phases (MatterSim energies)
├── mp_vaspdft.json ← Cached MP stable phases (DFT energies)
└── electride_candidates.json # Analysis results

Workflow States

Each structure progresses through these states in workflow_manager.py:

PENDING (structure passed pre-screening, ready for VASP)
↓
RELAX_RUNNING → RELAX_DONE → SC_RUNNING → PARCHG_RUNNING → ELF_RUNNING → ELF_DONE
↓ ↓ ↓ ↓ ↓ ↓
RELAX_FAILED (skip) SC_FAILED PARCHG_FAILED ELF_FAILED (success)
Note: SC_RUNNING, PARCHG_RUNNING, and ELF_RUNNING are all part of one SPE job
State transitions happen automatically as stage markers are detected

Note: Pre-screening (MatterSim + MP hull analysis) is done separately by prescreen.py. Only structures that pass pre-screening (E_hull < threshold) are loaded into workflow_manager.py.

Key behaviors:

  • Only structures that passed pre-screening are processed
  • Reduced SLURM jobs: 2 jobs per structure (1 Relax + 1 SPE) instead of 8 jobs
  • SPE job runs sequentially: SC -> PARCHG (5 energy windows) -> ELF in one script
  • Stage markers: SC_DONE, PARCHG_DONE, VASP_DONE track progress within SPE job
  • State transitions: Workflow manager detects markers and transitions states automatically
  • PARCHG for ALL materials: Following HT-electride methodology
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied)
  • Workflow manager automatically submits next structure when slots free up
  • Failed jobs don't block other structures
  • Max concurrent limit applies to total running structures

SPE Workflow Architecture

The unified SPE (SC-PARCHG-ELF) workflow uses a clean separation of concerns:

Python (workflow_manager.py) handles:

  • INCAR/POSCAR/POTCAR/KPOINTS for Relax, SC, ELF jobs
  • Structure loading from CIF files and symmetrization
  • Database state tracking and job orchestration
  • Directory structure creation

Helper script (generate_parchg_incars.py) handles:

  • PARCHG INCAR generation (requires parsing vasprun.xml-SC)
  • Band index calculation from NELECT and SOC parameters
  • FFT grid extraction (NGXF, NGYF, NGZF)
  • Called from bash after SC completes

Bash (job.sh in SPE/) handles:

  • Sequential execution: SC → PARCHG (5 types) → ELF
  • File copying between stages (CHGCAR-SC, WAVECAR-SC reused)
  • PARCHG output renaming (PARCHG → PARCHG-e0025, etc.)
  • PARCHG compression (PARCHG-* → PARCHG.tar.gz) to save disk space
  • Cleanup between stages to prevent VASP issues
  • Stage marker creation (SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE)

Why this design:

  • PARCHG is the ONLY calculation requiring runtime VASP output parsing
  • Keeps Python code IDE-friendly (no embedded heredocs)
  • Helper script is testable standalone
  • Other INCARs are straightforward pymatgen calls (no external scripts needed)

Monitoring

Option 1: Workflow Status Tool (Recommended)

# Overall summary
python workflow_status.py ./VASP_JOBS/workflow.json

Shows:

  • Total structures
  • Status breakdown (PENDING, RELAX_RUNNING, SC_RUNNING, etc.)
  • Currently running count
  • Completion percentage

Additional views:

# Running jobs with SLURM job IDs
python workflow_status.py workflow.json --running
# Failed structures (for debugging)
python workflow_status.py workflow.json --failed
# Composition-level summary
python workflow_status.py workflow.json --compositions
# Recently completed structures
python workflow_status.py workflow.json --completed --limit 20
# Filter by specific state
python workflow_status.py workflow.json --details --state SC_RUNNING

Option 2: Reattach to Tmux

# See live workflow output
tmux attach -t vaspflow
# View, then detach: Ctrl+B, then D

Option 3: Check SLURM Queue

# Check running jobs
squeue -u $USER# Check job history
sacct -S $(date --date="7 days ago" -I) -u $USER# Detailed job info
scontrol show job <JOBID>

Option 4: Manual Inspection

# View database directly
cat ./VASP_JOBS/workflow.json | jq '.structures | to_entries | map({id: .key, state: .value.state})'# Check specific job directorycd ./VASP_JOBS/Li10B1N3/Li10B1N3_s001/Relax
ls -lh
tail vasp_*.out
tail OSZICAR

Analyzing Results for Electride Candidates

After ELF calculations complete, analyze structures for electride characteristics using Bader topological analysis on both ELFCAR and PARCHG files.

New in v2.0: Incremental analysis with MatterSim e_above_hull integration, PyXtal database storage, and stricter candidate filtering.

Step 1: Initial Analysis (All Structures)

Recommended: Run analysis as a SLURM job (not on login node):

# Submit analysis job with defaults
bash submit_analysis.sh
# Custom settings
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# View results when complete
cat electride_analysis.csv

Output:

  • electride_analysis.csv - All analyzed structures with interstitial volumes
  • electride_data.db - PyXtal database with all structures

Step 2: Filter High-Quality Candidates

Apply stricter volume thresholds to identify high-quality electride candidates:

# Filter with default thresholds (20 ų)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# Custom thresholds (stricter)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 25 \
--min-band 25

Filtering Criteria:

  • max(e0025, e05, e10) >= min-energy (default: 20 ų)
  • max(band0, band1) >= min-band (default: 20 ų)
  • Removes duplicate structures
  • Adds PyXtal symmetry information (space groups)

Output:

  • electride_candidates.db - Filtered high-quality candidates with symmetry
  • electride_candidates.csv - CSV table for quick viewing

Step 3: Extract CIF Files

Extract CIF files for the filtered candidates:

# Extract from filtered database
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Output: electride_CIF/*.cif - One CIF file per candidate

Step 4: Query Database

Use ase db to query and filter candidates:

# View all candidates
ase db electride_candidates.db
# Sort by space group (high symmetry first)
ase db electride_candidates.db \
formula,space_group_number,e_above_hull \
-s space_group_number-
# Filter by stability (< 50 meV/atom)
ase db electride_candidates.db 'e_above_hull<0.05'# Show interstitial volumes
ase db electride_candidates.db \
formula,e0025,e05,e10,band0,band1,e_above_hull
# Cubic structures (space group >= 195)
ase db electride_candidates.db 'space_group_number>=195'# High interstitial volume (e0025 > 50 ų)
ase db electride_candidates.db 'e0025>50'

What the Analysis Does

Initial Analysis (analyze.py):

  1. Reads ELFCAR - electron localization function from VASP SPE directory
  2. Extracts PARCHG files from PARCHG.tar.gz (5 types):
    • PARCHG-band0: Valence band maximum (VBM)
    • PARCHG-band1: Second highest occupied band (VBM-1)
    • PARCHG-e0025: Energy window [-0.025, 0.025] eV around Fermi level
    • PARCHG-e05: Energy window [-0.5, 0.025] eV
    • PARCHG-e10: Energy window [-1.0, 0.025] eV
  3. Runs Bader analysis on ELFCAR and each PARCHG file
  4. Filters interstitial electrons - sites far from atoms with high localization
  5. Reports volumes of interstitial electron density (ų) for each type
  6. Adds stability data - reads e_above_hull from prescreening_stability.json
  7. Extracts spacegroup - from CONTCAR using PyXtal (adaptive tolerance)
  8. Saves to database - stores all structures in electride_data.db

Filtering (filter_comb_db.py):

  1. Applies volume thresholds - only keeps structures with substantial interstitial volumes
  2. Symmetrizes structures - uses PyXtal with adaptive tolerance (coarse→fine)
  3. Removes duplicates - identifies and filters redundant structures
  4. Adds space group info - from PyXtal symmetry analysis
  5. Creates unified database - electride_candidates.db with structures + volumes
  6. Exports CSV - electride_candidates.csv for quick viewing

Key Features (v2.0)

Incremental Analysis:

  • Automatically skips already-analyzed structures from CSV and database
  • Run repeatedly as new ELF calculations complete without re-processing
  • Perfect for monitoring ongoing workflows

Enhanced Electride Criteria:

  • Old criteria: ANY of (e0025 > 0 OR e05 > 0 OR e10 > 0 OR band0 > 0)
  • New criteria: ALL of (e0025 > 0 AND e05 > 0 AND e10 > 0 AND band0 > 0)
  • More stringent to reduce false positives

DFT Integration:

  • Reads DFT energy_above_hull from compute_dft_e_hull.py output
  • Results sorted by stability (lowest e_above_hull first)
  • Most stable electride candidates rise to the top

PyXtal Database:

  • Saves all analyzed structures to electride_data.db
  • Adaptive symmetrization (tolerances: 1e-5 to 0.5)
  • P1 fallback ensures 100% save success
  • Query-able for advanced analysis

Analysis Parameters

analyze.py:

  • --threshold: Minimum ELF value for electride detection (default: 0.6)
  • --bader-exe: Path to Bader executable (default: bader in PATH)
  • --output: Output CSV file name (default: electride_analysis.csv)
  • --pyxtal-db: PyXtal database file (default: electride_data.db)
  • --prescreening: MatterSim stability JSON (default: ./VASP_JOBS/prescreening_stability.json)
  • --workers: Number of parallel workers (default: CPU count)

filter_comb_db.py:

  • --min-energy: Minimum for max(e0025, e05, e10) in ų (default: 20)
  • --min-band: Minimum for max(band0, band1) in ų (default: 20)
  • --output: Output database (default: electride_candidates.db)
  • --output-csv: Output CSV (default: electride_candidates.csv)

Understanding Results

Initial Analysis (electride_analysis.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045
Li10B1N4_s003,Li10B1N4,0.00,0.00,0.00,5.28,0.00,12,0.068

Columns:

  • formula: Structure ID
  • composition: Chemical formula
  • e0025, e05, e10: Interstitial volumes (ų) from energy windows
  • band0, band1: Interstitial volumes (ų) from band-specific charges
  • spacegroup: PyXtal space group (1 = P1 fallback)
  • e_above_hull: MatterSim energy above hull (eV/atom)

Electride Criteria:

  • (e0025 > 0 OR e05 > 0) AND (e10 > 0 OR band0 > 0)

Filtered Candidates (electride_candidates.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045

Additional Filtering:

  • max(e0025, e05, e10) >= 20 ų (substantial energy window volume)
  • max(band0, band1) >= 20 ų (substantial band-specific volume)
  • Duplicates removed
  • Space group from PyXtal symmetry analysis

Interpreting volumes (in ų):

  • > 20: High-quality electride (passes filtering)
  • 0-20: Weak electride (filtered out by default)
  • High across multiple columns: Strong, robust electride character

Example interpretation:

  • Li10B1N4_s001: High-quality electride (all volumes > 20 ų, stable)
  • Li10B1N4_s002: Moderate electride (volumes > 12 ų, borderline)
  • Li10B1N4_s003: Not electride (very low volumes)

Sorting:

  • Both CSVs sorted by e_above_hull (low → high)
  • Most thermodynamically stable candidates appear first

Console output during analysis:

Total ELF_DONE: 100
Semiconductors (with PARCHG): 15
Metals (ELFCAR only): 85
(All structures analyzed with PARCHG in SPE workflow)
Analyzing: Li10B1N4_s001 (VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE)
Spacegroup: 166
*** ELECTRIDE CANDIDATE *** (e0025=32.62, e05=31.82, e10=31.31, band0=35.11, band1=0.00)
Analyzing: Li10B1N4_s003 (VASP_JOBS/Li10B1N4/Li10B1N4_s003/SPE)
Spacegroup: 139
Not electride (e0025=0.00, e05=0.00, e10=0.00, band0=5.28, band1=0.00)

Filter output:

======================================================================
Filtering Electride Database with Stricter Criteria
======================================================================
Criteria:
max(e0025, e05, e10) >= 20.0 ų
max(band0, band1) >= 20.0 ų
Processing structures...
Added 100 structures...
Using P1 fallback for Ba8S7_s024
Added 200 structures...
Filtering Summary:
Input structures: 6134
Filtered out (below thresholds): 4512
Duplicates removed: 89
Failed to process: 0
Added to output database: 1533

Incremental Analysis Workflow

# Day 1: 50 ELF calculations done
bash submit_analysis.sh
# Output: 50 structures analyzed# → electride_analysis.csv (50 structures)# → electride_data.db (50 structures)# Filter to get high-quality candidates
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 25 high-quality)# electride_candidates.csv# Day 2: 30 more ELF calculations done (total 80)
bash submit_analysis.sh
# Output: Only 30 new analyzed (skips existing 50)# → electride_analysis.csv updated (80 total, re-sorted)# → electride_data.db updated (80 total)# Re-filter with updated data
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 40 high-quality)# Day 3: 20 more ELF calculations done (total 100)
bash submit_analysis.sh
# Output: Only 20 new analyzed# → Final electride_analysis.csv (100 structures)# Final filtering
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: Final electride_candidates.db (e.g., 50 high-quality)# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Benefits:

  • Incremental analysis saves time (only analyzes new structures)
  • Filtering is fast (~2 min) and can be adjusted without re-running Bader
  • Database is query-able at any stage

Direct Analysis (Advanced)

The analysis uses Electride.py internally via analyze.py. For manual testing:

# Test on single structure (SPE workflow)cd VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE
python3 ../../../../Electride.py . --bader-exe ~/apps/Bader/bader
# Run full analysis with all options
python3 analyze.py \
--db VASP_JOBS/workflow.json \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv \
--pyxtal-db electride_data.db \
--prescreening VASP_JOBS/prescreening_stability.json \
--workers 32
# Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20

Requirements:

  • ELFCAR file (generated by VASP with LELF=True in SPE/)
  • PARCHG.tar.gz (5 files compressed, automatically extracted during analysis)
  • Bader executable (download from: https://theory.cm.utexas.edu/henkelman/code/bader/)
  • (Optional) prescreening_stability.json for MatterSim e_above_hull values

Output Files

Initial Analysis:

  1. electride_analysis.csv: All analyzed structures with volumes
  2. electride_data.db: PyXtal database with all structures
  3. electride_analysis_detailed.log: Full console output

Filtered Candidates:

  1. electride_candidates.csv: High-quality candidates (CSV table)
  2. electride_candidates.db: PyXtal database with filtered structures + volumes
  3. electride_CIF/: Directory with CIF files for candidates

Performance

Analysis (analyze.py):

  • Incremental mode: Only analyzes new structures (minutes for 30 new structures)
  • Full analysis: ~5-10 minutes per structure (PARCHG extraction + Bader analysis)
  • Database saves: ~1 second per structure (with adaptive tolerance)
  • Parallel processing: Scales with CPU cores (32 cores recommended)

Filtering (filter_comb_db.py):

  • Time: ~2 minutes for 6000 structures
  • PyXtal symmetry: ~0.02 sec per structure (vs AFLOW: ~0.45 sec)
  • Speedup: 14× faster than AFLOW-based workflow
  • Duplicate removal: Automatic during processing

DFT Energy Above Hull Calculation

After VASP relaxations complete, compute DFT-level thermodynamic stability using your VASP energies combined with Materials Project DFT energies for competing phases.

Energy Method Comparison

Compare energies between different calculation methods to validate pre-screening accuracy and diagnose any systematic biases:

# Run comparison (requires dft_stability_results.json)
bash run_compare_energy_method.sh \
--vasp-jobs ./VASP_JOBS \
--outlier-threshold 0.5
# Monitor job
squeue -u $USER| grep compare_energy
tail -f compare_energy_method_*.out
# Results will be in: VASP_JOBS/energy_method_comparison.json# Plots: mp_phases_comparison_*.png, generated_structures_comparison_*.png

What it compares:

  1. MP On-Hull Phases: MatterSim energies vs MP raw DFT energies
  2. Generated Structures: MatterSim energies vs VASP-DFT energies

Important: The generated structures comparison now uses dft_stability_results.json as the single source of truth for VASP energies. This ensures exact consistency with hull_comparison plots (same structures, same outlier filtering).

Key metrics:

  • Pearson correlation between methods
  • Mean Absolute Error (MAE)
  • Systematic bias detection
  • Helps diagnose non-linear hull behavior

Usage

# Submit DFT hull calculation (after VASP relaxations complete)
bash run_dft_e_hull.sh \
--vasp-jobs ./VASP_JOBS \
--output dft_stability_results.json \
--prescreen-results ./VASP_JOBS/prescreening_stability.json
# Monitor job
squeue -u $USER| grep dft_e_hull
tail -f dft_e_hull_*.out
# Hull comparison (MatterSim vs DFT) is automatically generated# if --prescreen-results is provided to compute_dft_e_hull.py# Results will be in: VASP_JOBS/hull_comparison.json# Plots: hull_comparison_scatter.png, hull_comparison_residuals.png

What It Does

  1. Scans for completed VASP relaxations (RELAX_DONE or later states)
  2. Extracts VASP energies from vasprun.xml
  3. Queries MP for stable phases only (is_stable=True) - much faster than querying all phases
  4. Uses single cache file (mp_vaspdft.json) with automatic subsystem handling
  5. Computes DFT energy_above_hull for each structure using PDEntry
  6. Outputsdft_stability_results.json with decomposition products

Output Format

{
"summary": {
"total_structures": 100,
"processed_successfully": 95,
"failed": 5,
"energy_reference": "DFT uncorrected (VASP-PBE + MP stable phases only)",
"mp_phase_selection": "stable_only (is_stable=True)",
"mp_functional_filter": "mixed_pbe_pbeU"
},
"results": [
{
"structure_id": "Li10B1N4_s001",
"composition": "Li10B1N4",
"chemsys": "B-Li-N",
"vasp_energy_per_atom": -3.45678,
"dft_energy_above_hull": 0.023,
"decomposition_products": "Li3N (0.714) + BN (0.286)",
"num_mp_stable_phases": 18,
"error": null
}
]
}

Validation: MatterSim vs DFT Hull Comparison

The compute_dft_e_hull.py script automatically validates pre-screening accuracy by comparing MatterSim vs DFT hull values when --prescreen-results is provided:

Statistical metrics:

  • Pearson correlation (how well MatterSim predicts DFT)
  • Mean Absolute Error (MAE)
  • Root Mean Square Error (RMSE)

Pre-screening performance:

  • True Positives: Correctly passed (stable in both)
  • False Positives: Incorrectly passed (unstable in DFT, wasted VASP)
  • True Negatives: Correctly filtered (unstable in both)
  • False Negatives: Incorrectly filtered (stable in DFT, missed!)
  • Precision, Recall, F1 Score
  • Computational savings (% VASP avoided)

Output: hull_comparison.json with detailed analysis

When to Use

  • After some VASP relaxations complete: Validate pre-screening accuracy early
  • Before publication: Get accurate DFT stability data
  • To identify outliers: Find structures that were incorrectly filtered/passed

Performance

  • Time: ~1-2 hours for 100 structures (mostly MP API queries)
  • Resources: 8 CPUs, 32GB RAM (for large systems)
  • Caching: Uses MP IDs from pre-screening cache to minimize API calls

Troubleshooting

Workflow Manager Not Running

Symptom: Jobs complete but database still shows RUNNING state

Check if manager job is running:

squeue -u $USER| grep vaspflow_manager

Solution: Restart workflow manager if stopped

bash run_workflow.sh --max-concurrent 10
# It will detect completed jobs and update states

Jobs Not Progressing

Check:

# Check workflow manager job
squeue -u $USER| grep vaspflow_manager
tail -f workflow_manager_*.out
# See what's completed
find ./VASP_JOBS -name "VASP_DONE"| wc -l
find ./VASP_JOBS -name "VASP_FAILED"| wc -l
# Check VASP jobs in queue
squeue -u $USER# Check database state
python workflow_status.py ./VASP_JOBS/workflow.json

Fix: Restart workflow manager if it stopped

bash run_workflow.sh --max-concurrent 10

Failed Jobs

# List all failures
python workflow_status.py workflow.json --failed
# Investigate specific failurecd ./VASP_JOBS/Li10B1N3/Li10B1N3_s003/Relax
tail -50 vasp_*.err
tail -50 OSZICAR
grep -i "error\|killed\|fail" vasp_*.out

Common failure causes:

  • Walltime limit hit (24 hours default)
  • Convergence issues (check OSZICAR)
  • Memory issues (check vasp_*.err)
  • POTCAR problems (check first few lines of vasp_*.out)

Resetting Failed Jobs for Retry

Use reset_failed_jobs.py to reset failed structures and retry them:

# Step 1: List all failed structures to understand what went wrong
python3 reset_failed_jobs.py --list
# Output shows failures grouped by stage:# RELAX_FAILED: 72 structures# SC_FAILED: 4 structures# PARCHG_FAILED: 4 structures# Step 2: Dry run to preview changes (recommended)
python3 reset_failed_jobs.py --dry-run --clean
# Step 3: Reset all failed jobs
python3 reset_failed_jobs.py --clean
# OR reset specific stage only
python3 reset_failed_jobs.py --stage RELAX --clean
python3 reset_failed_jobs.py --stage SC --clean
python3 reset_failed_jobs.py --stage PARCHG --clean
# Step 4: Resume workflow to retry
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10

What it does:

  • RELAX_FAILEDPENDING (retry from scratch)
  • SC_FAILEDRELAX_DONE (retry SC using existing relaxed structure)
  • PARCHG_FAILEDSC_DONE (retry PARCHG using existing SC results)
  • --clean flag removes VASP_FAILED markers for clean restart
  • Creates automatic backup: workflow.json.bak

Important: Investigate failure causes before blindly retrying. Some structures may have fundamental issues (bad geometry, unconverged, etc.) and will fail repeatedly.

POTCAR Not Found

# Check environmentecho$PMG_VASP_PSP_DIR# Verify structure
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
# Set if neededexport PMG_VASP_PSP_DIR=$HOME/apps/PBE64
# Add to ~/.bashrc to persist

Workflow Manager Job Issues

# Check if manager job is running
squeue -u $USER| grep vaspflow_manager
# View manager log
tail -100 workflow_manager_*.out
# Cancel stuck manager job
scancel <JOBID># Restart (database persists!)
bash run_workflow.sh --max-concurrent 10

Jobs Stuck in SLURM Queue

# Check job status
squeue -u $USER -o "%.18i %.9P %.30j %.8T %.10M %.6D %R"# Check why pending
squeue -u $USER -j <JOBID> --start
# Cancel stuck job if needed
scancel <JOBID># Workflow will mark it as failed on next check

Database Corruption

# Backup database
cp workflow.json workflow.json.backup
# Reinitialize (keeps existing directories)
python workflow_manager.py --init-only \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS
# Manually merge completed jobs from backup if needed

Parallel Pre-screening Results Missing

Symptom: After running submit_parallel_prescreen.sh, the prescreening_stability.json file is empty or only contains results from one batch.

Cause: Multiple parallel jobs writing to the same file cause race conditions and data loss.

Solution:

  1. Each batch processes a different subset of compositions using --start-composition (batch 0: comps 0-399, batch 1: 400-799, etc.)
  2. Each batch writes to its own file (prescreening_stability_batch0.json, etc.)
  3. After all jobs complete, merge them with merge_prescreen_batches.py:
# Check that all batch jobs completed
squeue -u $USER| grep prescreen # Should be empty# List batch result files
ls ./VASP_JOBS/prescreening_stability_batch*.json
ls ./VASP_JOBS/prescreening_structures_batch*.db
ls ./VASP_JOBS/mp_mattersim.json # Shared cache (not batch-specific)# Merge all batch results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# OR skip database merge (faster, JSON only)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS --skip-database
# Verify merged results
cat ./VASP_JOBS/prescreening_stability.json | jq '.metadata.total_structures'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Check shared MP cache
ls -lh ./VASP_JOBS/prescreening_structures.db # Check database exists

Prevention: Always run merge_prescreen_batches.py after parallel prescreening jobs complete.


Configuration

Key Parameters

Pre-screening (prescreen.py):

# Single GPU job
python prescreen.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0 \ # Max structures per composition
--batch-size 32 \ # Structures per batch (calculator reuse)
--mp-api-key YOUR_KEY \ # Materials Project API key
--hull-threshold 0.05 \ # E_hull threshold (eV/atom)
--device cuda \ # MatterSim device: cpu or cuda
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Automatically splits compositions across GPU nodes

VASP Workflow (workflow_manager.py):

python workflow_manager.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \ # Max structures running simultaneously
--max-compositions 20 \ # Limit number of compositions (optional)
--max-structures 0 \ # Max structures per composition
--check-interval 60 # Status check interval (seconds)

Recommendations:

  • Pre-screening:
    • --batch-size: 32 for A40/A100 GPUs (48GB VRAM), reduce to 16 for smaller GPUs
    • --hull-threshold: 0.1 eV/atom filters most unstable structures, use 0.05 for stricter filtering
    • --device: Use cuda for GPU acceleration (5-10× faster than CPU)
    • --mp-api-key: Get your free API key at https://next-gen.materialsproject.org/api
    • --pure-pbe: OPTIONAL flag to exclude PBE+U (recommended to OMIT for best accuracy)
      • Default (no flag): Mixed PBE/PBE+U (matches MP phase diagram methodology)
      • With flag: Pure GGA-PBE only (may reduce accuracy for transition metal systems)
    • MP API: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • Large datasets: Use submit_parallel_prescreen.sh to split across multiple GPUs
    • GPU memory: Set export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True in SLURM script
  • VASP Workflow:
  • --max-concurrent: 10-20 for typical HPC cluster
  • --check-interval: 60s is good balance
  • --max-compositions: Omit to process all
    • PyXtal: Structures automatically symmetrized for better convergence

SLURM Settings

Edit create_slurm_script() in workflow_manager.py (lines 163-176):

script=f"""#!/bin/bash#SBATCH --partition=Apus # Change partition#SBATCH --ntasks=32 # Change cores#SBATCH --time=1-00:00:00 # Change walltime (1 day)#SBATCH --mem=64G # Change memoery#SBATCH --output={job_dir}/vasp_%j.out#SBATCH --error={job_dir}/vasp_%j.err

VASP Input Settings

Edit create_vasp_inputs() in workflow_manager.py (lines 129-161):

Relax (line 135-142):

vis=MPRelaxSet(structure, user_incar_settings={
'EDIFF': 1e-6, # Energy convergence'EDIFFG': -0.01, # Force convergence (eV/Å)'NSW': 200, # Max ionic steps'PREC': 'Accurate',
'ISMEAR': 0, # Gaussian smearing'SIGMA': 0.05,
})

SC/Static (line 143-148):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LAECHG': True, # Write core charge'LCHARG': True, # Write CHGCAR
})

ELF (line 149-156):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LELF': True, # Calculate ELF'ADDGRID': True, # Finer FFT grid'NSW': 0, # No ionic steps'IBRION': -1,
})

Electride Detection Parameters

python analyze_completed.py \
--threshold 0.6 \ # ELF threshold (0.5-0.7 typical)
--min-distance 1.5 \ # Min distance from atoms (Å)
--volume-threshold 0.5 # Min interstitial volume (ų)

Performance

Per Structure (typical, 32 cores)

Pre-screening (MatterSim):

  • Relaxation: 10-30s per structure (CPU) or 5-10s (GPU)
  • MP query: One-time per chemical system (~2-5 min, cached)
  • Hull analysis: <1s per structure

VASP calculations:

  • Relax: 2-6 hours
  • SPE job (SC + PARCHG + ELF sequential): 5-10 hours
    • SC: 1-3 hours
    • PARCHG (5 sequential): 2.5-5 hours (5 × 30-60 min)
    • ELF: 1-2 hours
  • Total VASP time: 7-16 hours/structure
  • SLURM overhead: Reduced by 75% (2 jobs instead of 8 jobs per structure)

With pre-screening (filters ~60% structures):

  • Effective time: 3-6 hours/structure (accounting for filtered structures)
  • Savings: 40-60% of total VASP computation time

Example Workflow (100 structures, max_concurrent=10, with pre-screening)

TimeActionRunningCompletedNotes
T=0Pre-screen 100 structures00MatterSim + MP
T=1hPre-screening done0060 pass, 40 filtered out
T=1hSubmit first 10 Relax jobs100Only stable structures
T=5h10 Relax done, submit 10 SPE100SPE = SC+PARCHG+ELF
T=13h10 SPE done, submit new1010~8h per SPE job
...Repeat10...
T=53hAll 60 complete06040 filtered by pre-screening

Wall time: ~53 hours for 100 structures (60 pass pre-screening)
Core-hours: ~24,000 (60 structures × 12.5h avg × 32 cores / 2 efficiency)
SLURM jobs: 120 total (vs 480 with old workflow)
Savings: 40-60% computational time from pre-screening, 75% fewer SLURM jobs


MatterSim Pre-screening

Pre-screening uses the MatterSim ML potential to quickly evaluate thermodynamic stability before running expensive VASP calculations. This is done in a separate step using prescreen.py, which generates prescreening_stability.json with structures that pass the stability threshold.

How It Works

  1. MatterSim Relaxation: Structures relaxed in batches with calculator reuse for GPU memory efficiency
  2. MP Reference Phases Query: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • The modern mp_api.client misses many stable GGA phases needed for accurate hull calculations
    • Strict filtering: only accepts entries with -GGA or -GGA+U suffix in entry_id
    • Uses uncorrected_energy (raw DFT, no MP corrections) to match MatterSim energies
    • Optional --pure-pbe flag to exclude PBE+U (use pure GGA-PBE only)
  3. Re-relax MP Structures: MP GGA structures are re-relaxed with MatterSim for consistent energy reference
  4. Convex Hull: Build phase diagram using MatterSim energies with PDEntry
  5. Output: Generate prescreening_stability.json with structures that pass threshold
  6. VASP Workflow Filter: workflow_manager.py reads prescreening_stability.json and only processes structures with E_hull < threshold (default: 0.1 eV/atom)

Key Optimizations (NEW)

Batch Processing:

  • MatterSimCalculator reused across 32 structures per batch (configurable with --batch-size)
  • Dramatically reduces GPU memory overhead and initialization time
  • Automatic GPU memory cleanup between batches
  • Supports CUDA memory expansion: PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

Complete GGA Coverage with Legacy API:

  • Uses legacy pymatgen.ext.matproj.MPRester instead of modern mp_api.client
  • Modern API misses many stable GGA phases critical for accurate hull calculations
  • Queries ALL GGA/GGA+U entries via get_entries_in_chemsys()
  • Strict suffix filtering: Only accepts entries with -GGA or -GGA+U suffix in entry_id
  • Excludes r2SCAN, SCAN, and entries without explicit functional suffix
  • Uses uncorrected_energy (raw DFT, no MP anion/composition corrections)
  • Optional --pure-pbe flag to exclude PBE+U (for pure GGA-PBE calculations only)
  • More accurate phase diagrams with comprehensive GGA reference phases

Single Global Cache Files:

  • mp_mattersim.json: All MatterSim-relaxed MP phases with chemsys field
  • mp_vaspdft.json: All MP DFT energies with chemsys field
  • Automatically handles overlapping chemical systems (e.g., B-Li-N includes B, Li, N subsystems)
  • No more separate cache directories with duplicate data

Parallel Multi-GPU Processing:

  • submit_parallel_prescreen.sh: Splits compositions across multiple GPU nodes
  • Each batch job writes to unique files:
    • JSON: prescreening_stability_batch0.json, prescreening_stability_batch1.json, ...
    • Database: prescreening_structures_batch0.db, prescreening_structures_batch1.db, ...
  • MP cache is SHARED across all batches using dual-level file locking:
    • Single file: mp_mattersim.json (all batches read/write safely)
    • Cache I/O locking: mp_mattersim.lock prevents file corruption
    • Per-chemsys locking: mp_cache_{chemsys}.lock prevents duplicate MP queries
    • When Batch 0 queries Ba-O, other batches wait for it to finish
    • After Batch 0 completes, other batches read from cache (no duplicate API calls)
    • Lock files auto-cleaned after merge
  • After all jobs complete, run merge_prescreen_batches.py to combine results
  • Command-line configurable (use --help for full options)
  • Configurable compositions per job (default: 400)
  • Linear speedup with number of GPUs
  • Example: 2000 compositions → 5 GPU nodes = 5x faster
  • Critical: File locking ensures safe concurrent access to shared MP cache

PyXtal Symmetrization:

  • Structures automatically symmetrized before MatterSim relaxation
  • Same symmetrization applied to VASP initial structures in workflow_manager.py
  • Improves convergence and consistency between pre-screening and VASP

Configuration

# Option A: Single GPU job (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--device cuda \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Pure GGA-PBE only (omit for best accuracy)# View all options
bash submit_parallel_prescreen.sh --help
# Monitor parallel jobs
squeue -u $USER| grep prescreen
# After all parallel jobs complete, merge batch results
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# This combines:# - prescreening_stability_batch*.json → prescreening_stability.json# - prescreening_structures_batch*.db → prescreening_structures.db# - mp_mattersim.json is already shared (no merging needed)# Options:# --keep-batches: preserve individual batch files (default: delete after merge)# --skip-database: skip database merge, only merge JSON (faster)# Custom options for single GPU
bash run_prescreen.sh \
--batch-size 64 \ # Larger batch (requires more GPU memory)
--hull-threshold 0.05 \ # Stricter threshold (fewer pass)
--device cuda # Use GPU (much faster than CPU)# Check results and cache
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Number of cached MP phases
cat ./VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'# By chemical system# Step 2: Run VASP workflow (automatically filters based on pre-screening)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Note: VASP structures are automatically symmetrized with PyXtal before relaxation# This ensures consistency with pre-screening and improves convergence# By default, workflow_manager.py looks for:# ./VASP_JOBS/prescreening_stability.json## To use a different file:
bash run_workflow.sh --prescreen-results /path/to/custom_results.json
# To skip filtering (process all structures):# (Not recommended - remove prescreening_stability.json first)
bash run_workflow.sh # Will warn if file not found

Performance Impact

Overhead (with optimizations):

  • Single GPU: ~30-60 minutes for 100 structures across 10 chemical systems
  • Parallel (5 GPUs): ~10-15 minutes for same dataset (5x speedup)
  • Batch processing: 3-5x faster than previous per-structure calculator creation
  • Stable phases only: 10-20x faster MP queries (20-50 phases vs 500+ phases)
  • First structure in each chemical system takes longer (MP query + cache)
  • Subsequent structures in same system benefit from shared cache

Cache Efficiency:

  • Single mp_mattersim.json file (~1-5 MB) replaces multiple per-chemsys files
  • Automatic deduplication of overlapping subsystems
  • B-Li-N system includes: B, Li, N, B-Li, B-N, Li-N, B-Li-N (7 subsystems in 1 cache)

Savings:

  • Filters 50-80% of structures (typical)
  • Saves 4-10 VASP hours per filtered structure
  • Net savings: 40-60% of total computation time
  • Additional: Pre-screening itself is 3-5x faster with batch processing

Checking Pre-screening Results

# View pre-screening summary
cat VASP_JOBS/prescreening_stability.json | jq '.summary'# View individual results
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | { id: .structure_id, chemsys: .chemsys, E_hull: .energy_above_hull, passed: .passed_prescreening}'| less
# Count passed vs filtered
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==true)'| jq -s 'length'
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==false)'| jq -s 'length'

Pre-screening Utilities

Visualizing Energy Distribution

Use plot_e_above_hull.py to visualize the energy distribution and verify your threshold:

# Plot histogram of energy_above_hull values
python3 plot_e_above_hull.py \
--input ./VASP_JOBS/prescreening_stability.json \
--output histogram.png \
--bins 100 \
--max-energy 2.0

Extracting Stable Structures

Use extract_stable_structs.py to extract CIF files for structures that passed pre-screening:

# Extract CIF files for structures that passed pre-screening
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

Troubleshooting

All structures filtered out:

  • Threshold may be too strict (try --hull-threshold 0.2)
  • Check if MP API key is working
  • Verify MatterSim is installed correctly

Pre-screening taking too long:

  • Use GPU: --device cuda
  • MP cache should build once per chemical system
  • Check MP API rate limits (built-in backoff)

SLURM Job Management Reference

Basic SLURM Commands

ActionCommand
Submit workflow managerbash run_workflow.sh --max-concurrent 20
Check job queuesqueue -u $USER
Check specific jobsqueue -j <JOBID>
View job logtail -f workflow_manager_<JOBID>.out
Cancel jobscancel <JOBID>
Job historysacct -u $USER
Job detailsscontrol show job <JOBID>

Typical Usage Pattern

# Day 1: Start workflow
ssh your_cluster
cd /scratch/$USER/vaspflow
bash run_workflow.sh --max-concurrent 20
# Note the job ID, then log out# Day 2: Check progress (from anywhere)
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if manager is still running
squeue -u $USER| grep vaspflow_manager
# Check workflow progress
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# View manager log
tail -f workflow_manager_*.out

Files

FilePurpose
prescreen.pyMatterSim pre-screening with batch processing
run_prescreen.shSubmit single-GPU pre-screening wrapper
submit_prescreen.shSLURM script for single-GPU pre-screening
submit_parallel_prescreen.shNEW: Parallel multi-GPU prescreening across nodes
merge_prescreen_batches.pyNEW: Merge parallel batch results into single file
plot_e_above_hull.pyVisualize pre-screening energy distribution
extract_stable_structs.pyExtract CIF files for stable structures
workflow_manager.pyVASP workflow with PyXtal symmetrization
run_workflow.shSubmit workflow wrapper (user-facing)
submit_workflow_manager.shSLURM script for workflow manager
workflow_status.pyStatus checking and reporting
reset_failed_jobs.pyReset failed jobs to retry (RELAX/SC/PARCHG)
compute_dft_e_hull.pyCompute DFT energy_above_hull + MatterSim comparison
run_dft_e_hull.shSubmit DFT hull wrapper (user-facing)
submit_dft_e_hull.shSLURM script for DFT hull calculation
compare_energy_methods.pyCompare MatterSim vs DFT energies (uses dft_stability_results.json)
run_compare_energy_method.shSubmit energy method comparison wrapper
submit_compare_energy_method.shSLURM script for energy method comparison
analyze.pyOrchestrates electride analysis (calls Electride.py)
analyze.shSLURM script for analysis job
Electride.pyBader analysis on ELFCAR + PARCHG files
submit_analysis.shSubmit analysis wrapper (user-facing)
filter_comb_db.pyNEW: Filter candidates with stricter volume criteria + PyXtal symmetry
extract_electride_struct.pyExtract CIF files from filtered database
generate_parchg_incars.pyHelper script to generate PARCHG INCARs from vasprun.xml-SC

Key Features:

  • Unified SPE workflow: SC-PARCHG-ELF run sequentially in one SLURM job (2 jobs per structure vs 8)
  • Simplified directory structure: Relax/ and SPE/ subdirectories (vs 7+ subdirectories)
  • Stage markers: SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE track progress within SPE job
  • Reduced SLURM overhead: 75% fewer jobs submitted to queue
  • Clean code separation: Python for VASP inputs, bash for workflow orchestration
  • Helper script for PARCHG: Standalone script generates PARCHG INCARs (band indices from vasprun.xml-SC)
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied during relaxation)
  • Batch processing: prescreen.py reuses MatterSimCalculator across structures (3-5× faster)
  • Parallel prescreening: submit_parallel_prescreen.sh splits across GPU nodes (linear speedup)
  • Complete GGA coverage: Uses legacy pymatgen.ext.matproj.MPRester for comprehensive GGA/GGA+U phases
  • Strict functional filtering: Only accepts entries with -GGA or -GGA+U suffix (excludes r2SCAN/SCAN)
  • Uncorrected energies: Uses raw DFT energies (no MP corrections) for accurate hull calculations
  • Optional pure-pbe: --pure-pbe flag to filter MP entries to pure GGA-PBE only (exclude PBE+U)
  • Single cache files: mp_mattersim.json and mp_vaspdft.json in VASP_JOBS/ directory
  • PyXtal symmetrization: Automatic structure symmetrization in both prescreening and VASP workflow
  • Two-step electride filtering: Initial analysis saves all data, stricter filtering for high-quality candidates
  • Fast symmetry analysis: PyXtal-based filtering (14× faster than AFLOW)
  • Query-able database: ase db commands for filtering candidates by stability, symmetry, or volumes
  • PDEntry for hulls: Uses PDEntry instead of ComputedEntry for accurate phase diagram analysis
  • reset_failed_jobs.py resets failed VASP jobs to retry them without data loss
  • Integrated hull validation: compute_dft_e_hull.py automatically validates pre-screening accuracy with plots and statistics
  • Energy method comparison: compare_energy_methods.py uses dft_stability_results.json as single source of truth for exact consistency
  • User-friendly wrapper scripts provide consistent interface across all stages

Best Practices

  1. Run pre-screening first with prescreen.py to save 40-60% of VASP computation
  2. Use parallel prescreening (submit_parallel_prescreen.sh) for large datasets (>500 compositions)
  3. Merge batch results with merge_prescreen_batches.py after all parallel jobs complete
  4. Optimize batch size based on GPU memory: 32 for A40/A100 (48GB), 16 for smaller GPUs
  5. Wait for pre-screening to complete before starting VASP workflow
  6. Check pre-screening results (prescreening_stability.json) to verify threshold is appropriate
  7. Inspect cache files (mp_mattersim.json, mp_vaspdft.json) to verify MP data quality
  8. Submit both jobs as SLURM jobs (required on most HPC systems)
  9. Monitor from login node using workflow_status.py instead of viewing logs constantly
  10. Set reasonable max_concurrent (10-20) to avoid queue congestion
  11. Monitor your quota on /scratch periodically (cache files are now much smaller: ~1-5 MB total)
  12. Check failed jobs early to catch systematic issues
  13. Start small (test with 2-3 structures first using --max-compositions 2 --max-structures 2)
  14. Trust PyXtal symmetrization - structures are automatically symmetrized for consistency

Common Workflows

Production Run (Full Scale)

# Step 1: Pre-screening# Option A: Single GPU (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--device cuda \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets >500 compositions)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400
# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Auto-splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor with: squeue -u $USER | grep prescreen# Wait for completion, check and visualize results
cat VASP_JOBS/prescreening_stability.json | jq '.summary'
cat VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'
jq '.results[] | select(.passed_prescreening == true) | {structure_id, energy_above_hull}' VASP_JOBS/prescreening_stability.json
python3 plot_e_above_hull.py --bins 100
# (Optional) Extract stable structures for inspection
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# Step 2: VASP workflow (structures automatically symmetrized with PyXtal)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0 \
--check-interval 120
# Step 3: Analyze electride candidates
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# Step 4: Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# Step 5: Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Step 6: Query and explore
ase db electride_candidates.db
ase db electride_candidates.db 'e_above_hull<0.05' -s space_group_number-

Resume After Interruption

# Check if still running
squeue -u $USER| grep vaspflow_manager
# If stopped, restart - database persists
bash run_workflow.sh --max-concurrent 20

Integration with MatterGen

# 1. Generate structures with MatterGencd~/mattergen_test/ternary_electride
bash generate_ternary_csp.sh
# 2. Transfer to HPC scratchcd /scratch/$USER
cp -r ~/mattergen_test/results/ternary_csp_electrides mattergen_results/
# 3. Run pre-screening (as SLURM job)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Wait for pre-screening to complete
squeue -u $USER| grep prescreen
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 3b. Visualize and extract stable structures (optional)
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 4. Start VASP workflow (as SLURM job)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20
# 5. Monitor and analyze
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# 6. Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# 7. Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# 8. Query candidates
ase db electride_candidates.db 'e_above_hull<0.05'

Credits & References

Credits:

Tools & Libraries:

Key Paper:

@article{zhuComputationalDiscoveryInorganic2019,
title = {Computational {{Discovery}} of {{Inorganic Electrides}} from an {{Automated Screening}}},
author = {Zhu, Qiang and Frolov, Timofey and Choudhary, Kamal},
year = 2019,
month = nov,
journal = {Matter},
volume = {1},
number = {5},
pages = {1293--1303},
issn = {2590-2385},
doi = {10.1016/j.matt.2019.06.017},
}
@misc{tao2026acceleratedinorganicelectridesdiscovery,
title={Accelerated Inorganic Electrides Discovery by Generative Models and Hierarchical Screening}, author={Shuo Tao and Qiang Zhu},
year={2026},
eprint={2601.21077},
archivePrefix={arXiv},
primaryClass={cond-mat.mtrl-sci},
url={https://arxiv.org/abs/2601.21077}, }

About

DFT-HT Workflow for screening inorganic electrides

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ElectrideFlow - High-Throughput Inorganic Electride Discovery Workflow Accelerated by Generative Models and Hierarchical Prescreening

A four-stage intelligent workflow for high-throughput inorganic electride discovery on HPC clusters:

  1. Chemical Exploration - Generative AI models (MatterGen) explore composition space targeting electride-favorable chemistries
  2. Stability Screening - MatterSim (MLP) pre-screening filters structures by energy above hull before expensive DFT calculations
  3. Electride Identification - Coarse DFT relaxation with ELF & PARCHG topological analysis to identify electride candidates
  4. Refinement - Tight DFT relaxation with refined convex hull analysis for final candidate validation

Table of Contents


Features

MatterSim pre-screening - filter structures by energy_above_hull before VASP (saves 40-60% computation)
Batch processing - reuses MatterSimCalculator across structures for GPU memory efficiency
Parallel prescreening - split prescreening across multiple GPU nodes for faster throughput
Stable phases only - queries only on-hull MP phases for accurate, fast convex hull analysis
Smart caching - single global cache files (mp_mattersim.json, mp_vaspdft.json) handle overlapping systems
PyXtal symmetrization - automatic structure symmetrization for better VASP convergence
Unified SPE workflow - SC-PARCHG-ELF in single job (75% fewer SLURM jobs)
Batch submission - submit n structures at a time, auto-submit more as jobs complete
Dynamic monitoring - check status and submit new jobs automatically
Local JSON database - no network dependencies, works on HPC
Smart workflow - Pre-screen → Relax → SPE (SC + PARCHG + ELF sequential)
PARCHG analysis - band-edge charge density for accurate electride identification
Two-step filtering - initial analysis saves all, stricter filtering for candidates
Fast symmetry - PyXtal-based (14× faster than AFLOW)
Query-able database - ase db commands for candidate exploration
Pymatgen input generation - INCAR, POSCAR, POTCAR, KPOINTS
Bader analysis - identify electride candidates with topological analysis
Interrupt-safe - resume from any interruption
HPC-friendly - workflow manager runs as SLURM job


Quick Start

1. Setup Environment

# On HPC login nodecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# Copy files from your local machine:# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow orchestration# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Monitor workflow progress# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# Load CUDA runtime (check your HPC's available versions, need >= 11.8)
module load cuda/11.8
# Create conda environment
conda create -n mattersim python=3.10
conda activate mattersim
# Install PyTorch with matching CUDA version FIRST# (adjust cu118 to match your loaded CUDA module)
pip install torch==2.5.1+cu118 torchvision==0.20.1+cu118 torchaudio==2.5.1+cu118 \
--index-url https://download.pytorch.org/whl/cu118
pip install torch_scatter==2.1.2+pt25cu118 torch_sparse==0.6.18+pt25cu118 \
torch_cluster==1.6.3+pt25cu118 torch_spline_conv==1.2.2+pt25cu118 \
-f https://data.pyg.org/whl/torch-2.5.1+cu118.html
pip install torch-geometric==2.7.0 pytorch-lightning==2.0.6
# Install pymatgen/mp-api (pinned versions for MP API compatibility)
pip install pymatgen==2024.10.29 mp-api==0.43.0 monty==2024.7.30 emmet-core==0.84.10
# Install other dependencies
pip install numpy>=2.0 ase==3.23.0 pyxtal==1.1.1
# Install MatterSim last (--no-deps to avoid overriding torch versions)
pip install mattersim --no-deps
# Then install any missing mattersim deps that don't conflict:
pip install torch-ema torch-runstats torchmetrics
# Set environment variables in ~/.bashrcecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc

2. Pre-screening with MatterSim (NEW Step)

# Option A: Single GPU job (for small datasets)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--device cuda \
--compositions-per-job 400
# Optional: Add --pure-pbe flag to filter MP entries to pure GGA-PBE only# (default is mixed PBE/PBE+U which is recommended for best accuracy)# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Automatically splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# When done, check results
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# View cache files (single global files with chemsys field)
ls -lh ./VASP_JOBS/mp_mattersim.json
cat ./VASP_JOBS/mp_mattersim.json | jq '.[0]'# (Optional) Visualize results and extract CIF files
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

3. VASP Workflow (Run After Pre-screening)

# Submit VASP workflow manager (processes structures that passed pre-screening)cd /scratch/$USER/vaspflow
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Check job status
squeue -u $USER
tail -f workflow_manager_<JOBID>.out

4. Monitor Progress

cd /scratch/$USER/vaspflow
conda activate mattersim
# Check workflow manager job
squeue -u $USER# View workflow manager log
tail -f workflow_manager_<JOBID>.out
# Overall workflow status
python workflow_status.py ./VASP_JOBS/workflow.json
# Composition breakdown
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# Running VASP jobs
python workflow_status.py ./VASP_JOBS/workflow.json --running
# Failed structures
python workflow_status.py ./VASP_JOBS/workflow.json --failed

5. Analyze Results

# Submit electride analysis as SLURM job
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# When complete, view all analyzed structures
cat electride_analysis.csv
# Filter with stricter criteria to get high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# View filtered candidates
cat electride_candidates.csv
# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Query database for specific criteria
ase db electride_candidates.db 'e_above_hull<0.05'

Complete Setup Guide

Initial Setup (One-time)

# 1. SSH to HPC
ssh your_cluster
# 2. Create conda environment with all dependencies
conda create -n mattersim python=3.10
conda activate mattersim
conda install -c conda-forge pymatgen mp-api
pip install mattersim ase
# 3. Setup workspacecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# 4. Upload workflow scripts from your local machine# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Status monitoring# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# 5. Make scripts executable
chmod +x *.py *.sh
# 6. Set environment variablesecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc
# 7. Verify setup
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
echo"MP API Key: $MP_API_KEY"

Starting a Workflow

# 1. SSH to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# 2. Run pre-screening first (MatterSim + MP)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# Wait for pre-screening to complete (~1-2 hours for 100 structures)# Check results:
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 2b. (Optional) Visualize and extract stable structures
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 3. Submit VASP workflow manager (processes passing structures)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20 \
--max-structures 0
# 4. Monitor (optional)
squeue -u $USER# Check job status
tail -f workflow_manager_*.out # View log# You can now safely log out - workflow runs as SLURM job!

Resuming After Interruption

# SSH back to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if workflow manager is still running
squeue -u $USER| grep vaspflow_manager
# If not running, resubmit (database persists!)
bash run_workflow.sh --max-concurrent 20
# It automatically resumes from saved state in workflow.json

Workflow Overview

Architecture

MatterGen Structures
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 1: Pre-screening (prescreen.py + MatterSim) │
│ - SLURM job on compute node │
│ - Relax structures with MatterSim ML potential │
│ - Query MP for competing phases (cached per chemical system)│
│ - Compute energy_above_hull │
│ - Output: prescreening_stability.json │
│ - Filter: only E_hull < 0.1 eV/atom proceed to VASP │
└──────────────────────────────────────────────────────────────┘
↓
prescreening_stability.json
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 2: VASP Workflow (workflow_manager.py) │
│ - SLURM job on compute node │
│ - Initialize workflow database (JSON) │
│ - Batch submission loop: │
│ * Submit up to max_concurrent VASP jobs │
│ * Each structure: Relax → SC → PARCHG* → ELF (sequential)│
│ (* PARCHG only for semiconductors, band gap > 0.01 eV) │
│ * Monitor job completion every 60s │
│ * Submit new structures as slots free up │
└──────────────────────────────────────────────────────────────┘
↓
Analyze ELF + PARCHG Results (Bader analysis)
↓
Identify Electride Candidates

Job Chain Per Structure

  1. Pre-screening (MatterSim): Quick stability check → energy_above_hull
  2. Relax (VASP): Optimize geometry → CONTCAR
  3. SC (Self-Consistent): Accurate electronic structure → CHGCAR, WAVECAR, vasprun.xml
  4. PARCHG (all materials): Band-decomposed charge density → PARCHG-band0, PARCHG-band1, PARCHG-e0025, PARCHG-e05, PARCHG-e10
  5. ELF: Calculate electron localization → ELFCAR (PARCHG files copied here for analysis)

Directory Structure

/scratch/$USER/VASP_JOBS/
├── Li10B1N3/
│ ├── Li10B1N3_s001/
│ │ ├── Relax/
│ │ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ │ ├── job.sh
│ │ │ ├── CONTCAR (after completion)
│ │ │ ├── VASP_DONE (or VASP_FAILED)
│ │ │ └── vasp_*.out/err
│ │ └── SPE/ ← Unified SC-PARCHG-ELF directory
│ │ ├── job.sh ← Single SLURM job for all stages
│ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ ├── generate_parchg_incars.py ← Helper script (copied by workflow)
│ │ ├── SC_DONE, PARCHG_DONE ← Stage markers
│ │ ├── VASP_DONE (or VASP_FAILED) ← Final completion marker
│ │ ├── INCAR-SC, OSZICAR-SC, vasprun.xml-SC ← SC outputs
│ │ ├── INCAR-PARCHG-e0025, INCAR-PARCHG-e05, INCAR-PARCHG-e10
│ │ ├── INCAR-PARCHG-band0, INCAR-PARCHG-band1
│ │ ├── PARCHG.tar.gz ← Compressed PARCHG files
│ │ ├── INCAR-ELF
│ │ ├── ELFCAR ← ELF output
│ │ ├── ELF_DONE ← ELF stage marker
│ │ └── vasp_*.out/err
│ └── Li10B1N3_s002/
├── workflow.json # Job tracking database
├── prescreening_stability.json ← Pre-screening results
├── mp_mattersim.json ← Cached MP stable phases (MatterSim energies)
├── mp_vaspdft.json ← Cached MP stable phases (DFT energies)
└── electride_candidates.json # Analysis results

Workflow States

Each structure progresses through these states in workflow_manager.py:

PENDING (structure passed pre-screening, ready for VASP)
↓
RELAX_RUNNING → RELAX_DONE → SC_RUNNING → PARCHG_RUNNING → ELF_RUNNING → ELF_DONE
↓ ↓ ↓ ↓ ↓ ↓
RELAX_FAILED (skip) SC_FAILED PARCHG_FAILED ELF_FAILED (success)
Note: SC_RUNNING, PARCHG_RUNNING, and ELF_RUNNING are all part of one SPE job
State transitions happen automatically as stage markers are detected

Note: Pre-screening (MatterSim + MP hull analysis) is done separately by prescreen.py. Only structures that pass pre-screening (E_hull < threshold) are loaded into workflow_manager.py.

Key behaviors:

  • Only structures that passed pre-screening are processed
  • Reduced SLURM jobs: 2 jobs per structure (1 Relax + 1 SPE) instead of 8 jobs
  • SPE job runs sequentially: SC -> PARCHG (5 energy windows) -> ELF in one script
  • Stage markers: SC_DONE, PARCHG_DONE, VASP_DONE track progress within SPE job
  • State transitions: Workflow manager detects markers and transitions states automatically
  • PARCHG for ALL materials: Following HT-electride methodology
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied)
  • Workflow manager automatically submits next structure when slots free up
  • Failed jobs don't block other structures
  • Max concurrent limit applies to total running structures

SPE Workflow Architecture

The unified SPE (SC-PARCHG-ELF) workflow uses a clean separation of concerns:

Python (workflow_manager.py) handles:

  • INCAR/POSCAR/POTCAR/KPOINTS for Relax, SC, ELF jobs
  • Structure loading from CIF files and symmetrization
  • Database state tracking and job orchestration
  • Directory structure creation

Helper script (generate_parchg_incars.py) handles:

  • PARCHG INCAR generation (requires parsing vasprun.xml-SC)
  • Band index calculation from NELECT and SOC parameters
  • FFT grid extraction (NGXF, NGYF, NGZF)
  • Called from bash after SC completes

Bash (job.sh in SPE/) handles:

  • Sequential execution: SC → PARCHG (5 types) → ELF
  • File copying between stages (CHGCAR-SC, WAVECAR-SC reused)
  • PARCHG output renaming (PARCHG → PARCHG-e0025, etc.)
  • PARCHG compression (PARCHG-* → PARCHG.tar.gz) to save disk space
  • Cleanup between stages to prevent VASP issues
  • Stage marker creation (SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE)

Why this design:

  • PARCHG is the ONLY calculation requiring runtime VASP output parsing
  • Keeps Python code IDE-friendly (no embedded heredocs)
  • Helper script is testable standalone
  • Other INCARs are straightforward pymatgen calls (no external scripts needed)

Monitoring

Option 1: Workflow Status Tool (Recommended)

# Overall summary
python workflow_status.py ./VASP_JOBS/workflow.json

Shows:

  • Total structures
  • Status breakdown (PENDING, RELAX_RUNNING, SC_RUNNING, etc.)
  • Currently running count
  • Completion percentage

Additional views:

# Running jobs with SLURM job IDs
python workflow_status.py workflow.json --running
# Failed structures (for debugging)
python workflow_status.py workflow.json --failed
# Composition-level summary
python workflow_status.py workflow.json --compositions
# Recently completed structures
python workflow_status.py workflow.json --completed --limit 20
# Filter by specific state
python workflow_status.py workflow.json --details --state SC_RUNNING

Option 2: Reattach to Tmux

# See live workflow output
tmux attach -t vaspflow
# View, then detach: Ctrl+B, then D

Option 3: Check SLURM Queue

# Check running jobs
squeue -u $USER# Check job history
sacct -S $(date --date="7 days ago" -I) -u $USER# Detailed job info
scontrol show job <JOBID>

Option 4: Manual Inspection

# View database directly
cat ./VASP_JOBS/workflow.json | jq '.structures | to_entries | map({id: .key, state: .value.state})'# Check specific job directorycd ./VASP_JOBS/Li10B1N3/Li10B1N3_s001/Relax
ls -lh
tail vasp_*.out
tail OSZICAR

Analyzing Results for Electride Candidates

After ELF calculations complete, analyze structures for electride characteristics using Bader topological analysis on both ELFCAR and PARCHG files.

New in v2.0: Incremental analysis with MatterSim e_above_hull integration, PyXtal database storage, and stricter candidate filtering.

Step 1: Initial Analysis (All Structures)

Recommended: Run analysis as a SLURM job (not on login node):

# Submit analysis job with defaults
bash submit_analysis.sh
# Custom settings
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# View results when complete
cat electride_analysis.csv

Output:

  • electride_analysis.csv - All analyzed structures with interstitial volumes
  • electride_data.db - PyXtal database with all structures

Step 2: Filter High-Quality Candidates

Apply stricter volume thresholds to identify high-quality electride candidates:

# Filter with default thresholds (20 ų)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# Custom thresholds (stricter)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 25 \
--min-band 25

Filtering Criteria:

  • max(e0025, e05, e10) >= min-energy (default: 20 ų)
  • max(band0, band1) >= min-band (default: 20 ų)
  • Removes duplicate structures
  • Adds PyXtal symmetry information (space groups)

Output:

  • electride_candidates.db - Filtered high-quality candidates with symmetry
  • electride_candidates.csv - CSV table for quick viewing

Step 3: Extract CIF Files

Extract CIF files for the filtered candidates:

# Extract from filtered database
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Output: electride_CIF/*.cif - One CIF file per candidate

Step 4: Query Database

Use ase db to query and filter candidates:

# View all candidates
ase db electride_candidates.db
# Sort by space group (high symmetry first)
ase db electride_candidates.db \
formula,space_group_number,e_above_hull \
-s space_group_number-
# Filter by stability (< 50 meV/atom)
ase db electride_candidates.db 'e_above_hull<0.05'# Show interstitial volumes
ase db electride_candidates.db \
formula,e0025,e05,e10,band0,band1,e_above_hull
# Cubic structures (space group >= 195)
ase db electride_candidates.db 'space_group_number>=195'# High interstitial volume (e0025 > 50 ų)
ase db electride_candidates.db 'e0025>50'

What the Analysis Does

Initial Analysis (analyze.py):

  1. Reads ELFCAR - electron localization function from VASP SPE directory
  2. Extracts PARCHG files from PARCHG.tar.gz (5 types):
    • PARCHG-band0: Valence band maximum (VBM)
    • PARCHG-band1: Second highest occupied band (VBM-1)
    • PARCHG-e0025: Energy window [-0.025, 0.025] eV around Fermi level
    • PARCHG-e05: Energy window [-0.5, 0.025] eV
    • PARCHG-e10: Energy window [-1.0, 0.025] eV
  3. Runs Bader analysis on ELFCAR and each PARCHG file
  4. Filters interstitial electrons - sites far from atoms with high localization
  5. Reports volumes of interstitial electron density (ų) for each type
  6. Adds stability data - reads e_above_hull from prescreening_stability.json
  7. Extracts spacegroup - from CONTCAR using PyXtal (adaptive tolerance)
  8. Saves to database - stores all structures in electride_data.db

Filtering (filter_comb_db.py):

  1. Applies volume thresholds - only keeps structures with substantial interstitial volumes
  2. Symmetrizes structures - uses PyXtal with adaptive tolerance (coarse→fine)
  3. Removes duplicates - identifies and filters redundant structures
  4. Adds space group info - from PyXtal symmetry analysis
  5. Creates unified database - electride_candidates.db with structures + volumes
  6. Exports CSV - electride_candidates.csv for quick viewing

Key Features (v2.0)

Incremental Analysis:

  • Automatically skips already-analyzed structures from CSV and database
  • Run repeatedly as new ELF calculations complete without re-processing
  • Perfect for monitoring ongoing workflows

Enhanced Electride Criteria:

  • Old criteria: ANY of (e0025 > 0 OR e05 > 0 OR e10 > 0 OR band0 > 0)
  • New criteria: ALL of (e0025 > 0 AND e05 > 0 AND e10 > 0 AND band0 > 0)
  • More stringent to reduce false positives

DFT Integration:

  • Reads DFT energy_above_hull from compute_dft_e_hull.py output
  • Results sorted by stability (lowest e_above_hull first)
  • Most stable electride candidates rise to the top

PyXtal Database:

  • Saves all analyzed structures to electride_data.db
  • Adaptive symmetrization (tolerances: 1e-5 to 0.5)
  • P1 fallback ensures 100% save success
  • Query-able for advanced analysis

Analysis Parameters

analyze.py:

  • --threshold: Minimum ELF value for electride detection (default: 0.6)
  • --bader-exe: Path to Bader executable (default: bader in PATH)
  • --output: Output CSV file name (default: electride_analysis.csv)
  • --pyxtal-db: PyXtal database file (default: electride_data.db)
  • --prescreening: MatterSim stability JSON (default: ./VASP_JOBS/prescreening_stability.json)
  • --workers: Number of parallel workers (default: CPU count)

filter_comb_db.py:

  • --min-energy: Minimum for max(e0025, e05, e10) in ų (default: 20)
  • --min-band: Minimum for max(band0, band1) in ų (default: 20)
  • --output: Output database (default: electride_candidates.db)
  • --output-csv: Output CSV (default: electride_candidates.csv)

Understanding Results

Initial Analysis (electride_analysis.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045
Li10B1N4_s003,Li10B1N4,0.00,0.00,0.00,5.28,0.00,12,0.068

Columns:

  • formula: Structure ID
  • composition: Chemical formula
  • e0025, e05, e10: Interstitial volumes (ų) from energy windows
  • band0, band1: Interstitial volumes (ų) from band-specific charges
  • spacegroup: PyXtal space group (1 = P1 fallback)
  • e_above_hull: MatterSim energy above hull (eV/atom)

Electride Criteria:

  • (e0025 > 0 OR e05 > 0) AND (e10 > 0 OR band0 > 0)

Filtered Candidates (electride_candidates.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045

Additional Filtering:

  • max(e0025, e05, e10) >= 20 ų (substantial energy window volume)
  • max(band0, band1) >= 20 ų (substantial band-specific volume)
  • Duplicates removed
  • Space group from PyXtal symmetry analysis

Interpreting volumes (in ų):

  • > 20: High-quality electride (passes filtering)
  • 0-20: Weak electride (filtered out by default)
  • High across multiple columns: Strong, robust electride character

Example interpretation:

  • Li10B1N4_s001: High-quality electride (all volumes > 20 ų, stable)
  • Li10B1N4_s002: Moderate electride (volumes > 12 ų, borderline)
  • Li10B1N4_s003: Not electride (very low volumes)

Sorting:

  • Both CSVs sorted by e_above_hull (low → high)
  • Most thermodynamically stable candidates appear first

Console output during analysis:

Total ELF_DONE: 100
Semiconductors (with PARCHG): 15
Metals (ELFCAR only): 85
(All structures analyzed with PARCHG in SPE workflow)
Analyzing: Li10B1N4_s001 (VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE)
Spacegroup: 166
*** ELECTRIDE CANDIDATE *** (e0025=32.62, e05=31.82, e10=31.31, band0=35.11, band1=0.00)
Analyzing: Li10B1N4_s003 (VASP_JOBS/Li10B1N4/Li10B1N4_s003/SPE)
Spacegroup: 139
Not electride (e0025=0.00, e05=0.00, e10=0.00, band0=5.28, band1=0.00)

Filter output:

======================================================================
Filtering Electride Database with Stricter Criteria
======================================================================
Criteria:
max(e0025, e05, e10) >= 20.0 ų
max(band0, band1) >= 20.0 ų
Processing structures...
Added 100 structures...
Using P1 fallback for Ba8S7_s024
Added 200 structures...
Filtering Summary:
Input structures: 6134
Filtered out (below thresholds): 4512
Duplicates removed: 89
Failed to process: 0
Added to output database: 1533

Incremental Analysis Workflow

# Day 1: 50 ELF calculations done
bash submit_analysis.sh
# Output: 50 structures analyzed# → electride_analysis.csv (50 structures)# → electride_data.db (50 structures)# Filter to get high-quality candidates
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 25 high-quality)# electride_candidates.csv# Day 2: 30 more ELF calculations done (total 80)
bash submit_analysis.sh
# Output: Only 30 new analyzed (skips existing 50)# → electride_analysis.csv updated (80 total, re-sorted)# → electride_data.db updated (80 total)# Re-filter with updated data
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 40 high-quality)# Day 3: 20 more ELF calculations done (total 100)
bash submit_analysis.sh
# Output: Only 20 new analyzed# → Final electride_analysis.csv (100 structures)# Final filtering
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: Final electride_candidates.db (e.g., 50 high-quality)# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Benefits:

  • Incremental analysis saves time (only analyzes new structures)
  • Filtering is fast (~2 min) and can be adjusted without re-running Bader
  • Database is query-able at any stage

Direct Analysis (Advanced)

The analysis uses Electride.py internally via analyze.py. For manual testing:

# Test on single structure (SPE workflow)cd VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE
python3 ../../../../Electride.py . --bader-exe ~/apps/Bader/bader
# Run full analysis with all options
python3 analyze.py \
--db VASP_JOBS/workflow.json \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv \
--pyxtal-db electride_data.db \
--prescreening VASP_JOBS/prescreening_stability.json \
--workers 32
# Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20

Requirements:

  • ELFCAR file (generated by VASP with LELF=True in SPE/)
  • PARCHG.tar.gz (5 files compressed, automatically extracted during analysis)
  • Bader executable (download from: https://theory.cm.utexas.edu/henkelman/code/bader/)
  • (Optional) prescreening_stability.json for MatterSim e_above_hull values

Output Files

Initial Analysis:

  1. electride_analysis.csv: All analyzed structures with volumes
  2. electride_data.db: PyXtal database with all structures
  3. electride_analysis_detailed.log: Full console output

Filtered Candidates:

  1. electride_candidates.csv: High-quality candidates (CSV table)
  2. electride_candidates.db: PyXtal database with filtered structures + volumes
  3. electride_CIF/: Directory with CIF files for candidates

Performance

Analysis (analyze.py):

  • Incremental mode: Only analyzes new structures (minutes for 30 new structures)
  • Full analysis: ~5-10 minutes per structure (PARCHG extraction + Bader analysis)
  • Database saves: ~1 second per structure (with adaptive tolerance)
  • Parallel processing: Scales with CPU cores (32 cores recommended)

Filtering (filter_comb_db.py):

  • Time: ~2 minutes for 6000 structures
  • PyXtal symmetry: ~0.02 sec per structure (vs AFLOW: ~0.45 sec)
  • Speedup: 14× faster than AFLOW-based workflow
  • Duplicate removal: Automatic during processing

DFT Energy Above Hull Calculation

After VASP relaxations complete, compute DFT-level thermodynamic stability using your VASP energies combined with Materials Project DFT energies for competing phases.

Energy Method Comparison

Compare energies between different calculation methods to validate pre-screening accuracy and diagnose any systematic biases:

# Run comparison (requires dft_stability_results.json)
bash run_compare_energy_method.sh \
--vasp-jobs ./VASP_JOBS \
--outlier-threshold 0.5
# Monitor job
squeue -u $USER| grep compare_energy
tail -f compare_energy_method_*.out
# Results will be in: VASP_JOBS/energy_method_comparison.json# Plots: mp_phases_comparison_*.png, generated_structures_comparison_*.png

What it compares:

  1. MP On-Hull Phases: MatterSim energies vs MP raw DFT energies
  2. Generated Structures: MatterSim energies vs VASP-DFT energies

Important: The generated structures comparison now uses dft_stability_results.json as the single source of truth for VASP energies. This ensures exact consistency with hull_comparison plots (same structures, same outlier filtering).

Key metrics:

  • Pearson correlation between methods
  • Mean Absolute Error (MAE)
  • Systematic bias detection
  • Helps diagnose non-linear hull behavior

Usage

# Submit DFT hull calculation (after VASP relaxations complete)
bash run_dft_e_hull.sh \
--vasp-jobs ./VASP_JOBS \
--output dft_stability_results.json \
--prescreen-results ./VASP_JOBS/prescreening_stability.json
# Monitor job
squeue -u $USER| grep dft_e_hull
tail -f dft_e_hull_*.out
# Hull comparison (MatterSim vs DFT) is automatically generated# if --prescreen-results is provided to compute_dft_e_hull.py# Results will be in: VASP_JOBS/hull_comparison.json# Plots: hull_comparison_scatter.png, hull_comparison_residuals.png

What It Does

  1. Scans for completed VASP relaxations (RELAX_DONE or later states)
  2. Extracts VASP energies from vasprun.xml
  3. Queries MP for stable phases only (is_stable=True) - much faster than querying all phases
  4. Uses single cache file (mp_vaspdft.json) with automatic subsystem handling
  5. Computes DFT energy_above_hull for each structure using PDEntry
  6. Outputsdft_stability_results.json with decomposition products

Output Format

{
"summary": {
"total_structures": 100,
"processed_successfully": 95,
"failed": 5,
"energy_reference": "DFT uncorrected (VASP-PBE + MP stable phases only)",
"mp_phase_selection": "stable_only (is_stable=True)",
"mp_functional_filter": "mixed_pbe_pbeU"
},
"results": [
{
"structure_id": "Li10B1N4_s001",
"composition": "Li10B1N4",
"chemsys": "B-Li-N",
"vasp_energy_per_atom": -3.45678,
"dft_energy_above_hull": 0.023,
"decomposition_products": "Li3N (0.714) + BN (0.286)",
"num_mp_stable_phases": 18,
"error": null
}
]
}

Validation: MatterSim vs DFT Hull Comparison

The compute_dft_e_hull.py script automatically validates pre-screening accuracy by comparing MatterSim vs DFT hull values when --prescreen-results is provided:

Statistical metrics:

  • Pearson correlation (how well MatterSim predicts DFT)
  • Mean Absolute Error (MAE)
  • Root Mean Square Error (RMSE)

Pre-screening performance:

  • True Positives: Correctly passed (stable in both)
  • False Positives: Incorrectly passed (unstable in DFT, wasted VASP)
  • True Negatives: Correctly filtered (unstable in both)
  • False Negatives: Incorrectly filtered (stable in DFT, missed!)
  • Precision, Recall, F1 Score
  • Computational savings (% VASP avoided)

Output: hull_comparison.json with detailed analysis

When to Use

  • After some VASP relaxations complete: Validate pre-screening accuracy early
  • Before publication: Get accurate DFT stability data
  • To identify outliers: Find structures that were incorrectly filtered/passed

Performance

  • Time: ~1-2 hours for 100 structures (mostly MP API queries)
  • Resources: 8 CPUs, 32GB RAM (for large systems)
  • Caching: Uses MP IDs from pre-screening cache to minimize API calls

Troubleshooting

Workflow Manager Not Running

Symptom: Jobs complete but database still shows RUNNING state

Check if manager job is running:

squeue -u $USER| grep vaspflow_manager

Solution: Restart workflow manager if stopped

bash run_workflow.sh --max-concurrent 10
# It will detect completed jobs and update states

Jobs Not Progressing

Check:

# Check workflow manager job
squeue -u $USER| grep vaspflow_manager
tail -f workflow_manager_*.out
# See what's completed
find ./VASP_JOBS -name "VASP_DONE"| wc -l
find ./VASP_JOBS -name "VASP_FAILED"| wc -l
# Check VASP jobs in queue
squeue -u $USER# Check database state
python workflow_status.py ./VASP_JOBS/workflow.json

Fix: Restart workflow manager if it stopped

bash run_workflow.sh --max-concurrent 10

Failed Jobs

# List all failures
python workflow_status.py workflow.json --failed
# Investigate specific failurecd ./VASP_JOBS/Li10B1N3/Li10B1N3_s003/Relax
tail -50 vasp_*.err
tail -50 OSZICAR
grep -i "error\|killed\|fail" vasp_*.out

Common failure causes:

  • Walltime limit hit (24 hours default)
  • Convergence issues (check OSZICAR)
  • Memory issues (check vasp_*.err)
  • POTCAR problems (check first few lines of vasp_*.out)

Resetting Failed Jobs for Retry

Use reset_failed_jobs.py to reset failed structures and retry them:

# Step 1: List all failed structures to understand what went wrong
python3 reset_failed_jobs.py --list
# Output shows failures grouped by stage:# RELAX_FAILED: 72 structures# SC_FAILED: 4 structures# PARCHG_FAILED: 4 structures# Step 2: Dry run to preview changes (recommended)
python3 reset_failed_jobs.py --dry-run --clean
# Step 3: Reset all failed jobs
python3 reset_failed_jobs.py --clean
# OR reset specific stage only
python3 reset_failed_jobs.py --stage RELAX --clean
python3 reset_failed_jobs.py --stage SC --clean
python3 reset_failed_jobs.py --stage PARCHG --clean
# Step 4: Resume workflow to retry
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10

What it does:

  • RELAX_FAILEDPENDING (retry from scratch)
  • SC_FAILEDRELAX_DONE (retry SC using existing relaxed structure)
  • PARCHG_FAILEDSC_DONE (retry PARCHG using existing SC results)
  • --clean flag removes VASP_FAILED markers for clean restart
  • Creates automatic backup: workflow.json.bak

Important: Investigate failure causes before blindly retrying. Some structures may have fundamental issues (bad geometry, unconverged, etc.) and will fail repeatedly.

POTCAR Not Found

# Check environmentecho$PMG_VASP_PSP_DIR# Verify structure
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
# Set if neededexport PMG_VASP_PSP_DIR=$HOME/apps/PBE64
# Add to ~/.bashrc to persist

Workflow Manager Job Issues

# Check if manager job is running
squeue -u $USER| grep vaspflow_manager
# View manager log
tail -100 workflow_manager_*.out
# Cancel stuck manager job
scancel <JOBID># Restart (database persists!)
bash run_workflow.sh --max-concurrent 10

Jobs Stuck in SLURM Queue

# Check job status
squeue -u $USER -o "%.18i %.9P %.30j %.8T %.10M %.6D %R"# Check why pending
squeue -u $USER -j <JOBID> --start
# Cancel stuck job if needed
scancel <JOBID># Workflow will mark it as failed on next check

Database Corruption

# Backup database
cp workflow.json workflow.json.backup
# Reinitialize (keeps existing directories)
python workflow_manager.py --init-only \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS
# Manually merge completed jobs from backup if needed

Parallel Pre-screening Results Missing

Symptom: After running submit_parallel_prescreen.sh, the prescreening_stability.json file is empty or only contains results from one batch.

Cause: Multiple parallel jobs writing to the same file cause race conditions and data loss.

Solution:

  1. Each batch processes a different subset of compositions using --start-composition (batch 0: comps 0-399, batch 1: 400-799, etc.)
  2. Each batch writes to its own file (prescreening_stability_batch0.json, etc.)
  3. After all jobs complete, merge them with merge_prescreen_batches.py:
# Check that all batch jobs completed
squeue -u $USER| grep prescreen # Should be empty# List batch result files
ls ./VASP_JOBS/prescreening_stability_batch*.json
ls ./VASP_JOBS/prescreening_structures_batch*.db
ls ./VASP_JOBS/mp_mattersim.json # Shared cache (not batch-specific)# Merge all batch results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# OR skip database merge (faster, JSON only)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS --skip-database
# Verify merged results
cat ./VASP_JOBS/prescreening_stability.json | jq '.metadata.total_structures'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Check shared MP cache
ls -lh ./VASP_JOBS/prescreening_structures.db # Check database exists

Prevention: Always run merge_prescreen_batches.py after parallel prescreening jobs complete.


Configuration

Key Parameters

Pre-screening (prescreen.py):

# Single GPU job
python prescreen.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0 \ # Max structures per composition
--batch-size 32 \ # Structures per batch (calculator reuse)
--mp-api-key YOUR_KEY \ # Materials Project API key
--hull-threshold 0.05 \ # E_hull threshold (eV/atom)
--device cuda \ # MatterSim device: cpu or cuda
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Automatically splits compositions across GPU nodes

VASP Workflow (workflow_manager.py):

python workflow_manager.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \ # Max structures running simultaneously
--max-compositions 20 \ # Limit number of compositions (optional)
--max-structures 0 \ # Max structures per composition
--check-interval 60 # Status check interval (seconds)

Recommendations:

  • Pre-screening:
    • --batch-size: 32 for A40/A100 GPUs (48GB VRAM), reduce to 16 for smaller GPUs
    • --hull-threshold: 0.1 eV/atom filters most unstable structures, use 0.05 for stricter filtering
    • --device: Use cuda for GPU acceleration (5-10× faster than CPU)
    • --mp-api-key: Get your free API key at https://next-gen.materialsproject.org/api
    • --pure-pbe: OPTIONAL flag to exclude PBE+U (recommended to OMIT for best accuracy)
      • Default (no flag): Mixed PBE/PBE+U (matches MP phase diagram methodology)
      • With flag: Pure GGA-PBE only (may reduce accuracy for transition metal systems)
    • MP API: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • Large datasets: Use submit_parallel_prescreen.sh to split across multiple GPUs
    • GPU memory: Set export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True in SLURM script
  • VASP Workflow:
  • --max-concurrent: 10-20 for typical HPC cluster
  • --check-interval: 60s is good balance
  • --max-compositions: Omit to process all
    • PyXtal: Structures automatically symmetrized for better convergence

SLURM Settings

Edit create_slurm_script() in workflow_manager.py (lines 163-176):

script=f"""#!/bin/bash#SBATCH --partition=Apus # Change partition#SBATCH --ntasks=32 # Change cores#SBATCH --time=1-00:00:00 # Change walltime (1 day)#SBATCH --mem=64G # Change memoery#SBATCH --output={job_dir}/vasp_%j.out#SBATCH --error={job_dir}/vasp_%j.err

VASP Input Settings

Edit create_vasp_inputs() in workflow_manager.py (lines 129-161):

Relax (line 135-142):

vis=MPRelaxSet(structure, user_incar_settings={
'EDIFF': 1e-6, # Energy convergence'EDIFFG': -0.01, # Force convergence (eV/Å)'NSW': 200, # Max ionic steps'PREC': 'Accurate',
'ISMEAR': 0, # Gaussian smearing'SIGMA': 0.05,
})

SC/Static (line 143-148):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LAECHG': True, # Write core charge'LCHARG': True, # Write CHGCAR
})

ELF (line 149-156):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LELF': True, # Calculate ELF'ADDGRID': True, # Finer FFT grid'NSW': 0, # No ionic steps'IBRION': -1,
})

Electride Detection Parameters

python analyze_completed.py \
--threshold 0.6 \ # ELF threshold (0.5-0.7 typical)
--min-distance 1.5 \ # Min distance from atoms (Å)
--volume-threshold 0.5 # Min interstitial volume (ų)

Performance

Per Structure (typical, 32 cores)

Pre-screening (MatterSim):

  • Relaxation: 10-30s per structure (CPU) or 5-10s (GPU)
  • MP query: One-time per chemical system (~2-5 min, cached)
  • Hull analysis: <1s per structure

VASP calculations:

  • Relax: 2-6 hours
  • SPE job (SC + PARCHG + ELF sequential): 5-10 hours
    • SC: 1-3 hours
    • PARCHG (5 sequential): 2.5-5 hours (5 × 30-60 min)
    • ELF: 1-2 hours
  • Total VASP time: 7-16 hours/structure
  • SLURM overhead: Reduced by 75% (2 jobs instead of 8 jobs per structure)

With pre-screening (filters ~60% structures):

  • Effective time: 3-6 hours/structure (accounting for filtered structures)
  • Savings: 40-60% of total VASP computation time

Example Workflow (100 structures, max_concurrent=10, with pre-screening)

TimeActionRunningCompletedNotes
T=0Pre-screen 100 structures00MatterSim + MP
T=1hPre-screening done0060 pass, 40 filtered out
T=1hSubmit first 10 Relax jobs100Only stable structures
T=5h10 Relax done, submit 10 SPE100SPE = SC+PARCHG+ELF
T=13h10 SPE done, submit new1010~8h per SPE job
...Repeat10...
T=53hAll 60 complete06040 filtered by pre-screening

Wall time: ~53 hours for 100 structures (60 pass pre-screening)
Core-hours: ~24,000 (60 structures × 12.5h avg × 32 cores / 2 efficiency)
SLURM jobs: 120 total (vs 480 with old workflow)
Savings: 40-60% computational time from pre-screening, 75% fewer SLURM jobs


MatterSim Pre-screening

Pre-screening uses the MatterSim ML potential to quickly evaluate thermodynamic stability before running expensive VASP calculations. This is done in a separate step using prescreen.py, which generates prescreening_stability.json with structures that pass the stability threshold.

How It Works

  1. MatterSim Relaxation: Structures relaxed in batches with calculator reuse for GPU memory efficiency
  2. MP Reference Phases Query: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • The modern mp_api.client misses many stable GGA phases needed for accurate hull calculations
    • Strict filtering: only accepts entries with -GGA or -GGA+U suffix in entry_id
    • Uses uncorrected_energy (raw DFT, no MP corrections) to match MatterSim energies
    • Optional --pure-pbe flag to exclude PBE+U (use pure GGA-PBE only)
  3. Re-relax MP Structures: MP GGA structures are re-relaxed with MatterSim for consistent energy reference
  4. Convex Hull: Build phase diagram using MatterSim energies with PDEntry
  5. Output: Generate prescreening_stability.json with structures that pass threshold
  6. VASP Workflow Filter: workflow_manager.py reads prescreening_stability.json and only processes structures with E_hull < threshold (default: 0.1 eV/atom)

Key Optimizations (NEW)

Batch Processing:

  • MatterSimCalculator reused across 32 structures per batch (configurable with --batch-size)
  • Dramatically reduces GPU memory overhead and initialization time
  • Automatic GPU memory cleanup between batches
  • Supports CUDA memory expansion: PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

Complete GGA Coverage with Legacy API:

  • Uses legacy pymatgen.ext.matproj.MPRester instead of modern mp_api.client
  • Modern API misses many stable GGA phases critical for accurate hull calculations
  • Queries ALL GGA/GGA+U entries via get_entries_in_chemsys()
  • Strict suffix filtering: Only accepts entries with -GGA or -GGA+U suffix in entry_id
  • Excludes r2SCAN, SCAN, and entries without explicit functional suffix
  • Uses uncorrected_energy (raw DFT, no MP anion/composition corrections)
  • Optional --pure-pbe flag to exclude PBE+U (for pure GGA-PBE calculations only)
  • More accurate phase diagrams with comprehensive GGA reference phases

Single Global Cache Files:

  • mp_mattersim.json: All MatterSim-relaxed MP phases with chemsys field
  • mp_vaspdft.json: All MP DFT energies with chemsys field
  • Automatically handles overlapping chemical systems (e.g., B-Li-N includes B, Li, N subsystems)
  • No more separate cache directories with duplicate data

Parallel Multi-GPU Processing:

  • submit_parallel_prescreen.sh: Splits compositions across multiple GPU nodes
  • Each batch job writes to unique files:
    • JSON: prescreening_stability_batch0.json, prescreening_stability_batch1.json, ...
    • Database: prescreening_structures_batch0.db, prescreening_structures_batch1.db, ...
  • MP cache is SHARED across all batches using dual-level file locking:
    • Single file: mp_mattersim.json (all batches read/write safely)
    • Cache I/O locking: mp_mattersim.lock prevents file corruption
    • Per-chemsys locking: mp_cache_{chemsys}.lock prevents duplicate MP queries
    • When Batch 0 queries Ba-O, other batches wait for it to finish
    • After Batch 0 completes, other batches read from cache (no duplicate API calls)
    • Lock files auto-cleaned after merge
  • After all jobs complete, run merge_prescreen_batches.py to combine results
  • Command-line configurable (use --help for full options)
  • Configurable compositions per job (default: 400)
  • Linear speedup with number of GPUs
  • Example: 2000 compositions → 5 GPU nodes = 5x faster
  • Critical: File locking ensures safe concurrent access to shared MP cache

PyXtal Symmetrization:

  • Structures automatically symmetrized before MatterSim relaxation
  • Same symmetrization applied to VASP initial structures in workflow_manager.py
  • Improves convergence and consistency between pre-screening and VASP

Configuration

# Option A: Single GPU job (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--device cuda \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Pure GGA-PBE only (omit for best accuracy)# View all options
bash submit_parallel_prescreen.sh --help
# Monitor parallel jobs
squeue -u $USER| grep prescreen
# After all parallel jobs complete, merge batch results
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# This combines:# - prescreening_stability_batch*.json → prescreening_stability.json# - prescreening_structures_batch*.db → prescreening_structures.db# - mp_mattersim.json is already shared (no merging needed)# Options:# --keep-batches: preserve individual batch files (default: delete after merge)# --skip-database: skip database merge, only merge JSON (faster)# Custom options for single GPU
bash run_prescreen.sh \
--batch-size 64 \ # Larger batch (requires more GPU memory)
--hull-threshold 0.05 \ # Stricter threshold (fewer pass)
--device cuda # Use GPU (much faster than CPU)# Check results and cache
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Number of cached MP phases
cat ./VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'# By chemical system# Step 2: Run VASP workflow (automatically filters based on pre-screening)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Note: VASP structures are automatically symmetrized with PyXtal before relaxation# This ensures consistency with pre-screening and improves convergence# By default, workflow_manager.py looks for:# ./VASP_JOBS/prescreening_stability.json## To use a different file:
bash run_workflow.sh --prescreen-results /path/to/custom_results.json
# To skip filtering (process all structures):# (Not recommended - remove prescreening_stability.json first)
bash run_workflow.sh # Will warn if file not found

Performance Impact

Overhead (with optimizations):

  • Single GPU: ~30-60 minutes for 100 structures across 10 chemical systems
  • Parallel (5 GPUs): ~10-15 minutes for same dataset (5x speedup)
  • Batch processing: 3-5x faster than previous per-structure calculator creation
  • Stable phases only: 10-20x faster MP queries (20-50 phases vs 500+ phases)
  • First structure in each chemical system takes longer (MP query + cache)
  • Subsequent structures in same system benefit from shared cache

Cache Efficiency:

  • Single mp_mattersim.json file (~1-5 MB) replaces multiple per-chemsys files
  • Automatic deduplication of overlapping subsystems
  • B-Li-N system includes: B, Li, N, B-Li, B-N, Li-N, B-Li-N (7 subsystems in 1 cache)

Savings:

  • Filters 50-80% of structures (typical)
  • Saves 4-10 VASP hours per filtered structure
  • Net savings: 40-60% of total computation time
  • Additional: Pre-screening itself is 3-5x faster with batch processing

Checking Pre-screening Results

# View pre-screening summary
cat VASP_JOBS/prescreening_stability.json | jq '.summary'# View individual results
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | { id: .structure_id, chemsys: .chemsys, E_hull: .energy_above_hull, passed: .passed_prescreening}'| less
# Count passed vs filtered
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==true)'| jq -s 'length'
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==false)'| jq -s 'length'

Pre-screening Utilities

Visualizing Energy Distribution

Use plot_e_above_hull.py to visualize the energy distribution and verify your threshold:

# Plot histogram of energy_above_hull values
python3 plot_e_above_hull.py \
--input ./VASP_JOBS/prescreening_stability.json \
--output histogram.png \
--bins 100 \
--max-energy 2.0

Extracting Stable Structures

Use extract_stable_structs.py to extract CIF files for structures that passed pre-screening:

# Extract CIF files for structures that passed pre-screening
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

Troubleshooting

All structures filtered out:

  • Threshold may be too strict (try --hull-threshold 0.2)
  • Check if MP API key is working
  • Verify MatterSim is installed correctly

Pre-screening taking too long:

  • Use GPU: --device cuda
  • MP cache should build once per chemical system
  • Check MP API rate limits (built-in backoff)

SLURM Job Management Reference

Basic SLURM Commands

ActionCommand
Submit workflow managerbash run_workflow.sh --max-concurrent 20
Check job queuesqueue -u $USER
Check specific jobsqueue -j <JOBID>
View job logtail -f workflow_manager_<JOBID>.out
Cancel jobscancel <JOBID>
Job historysacct -u $USER
Job detailsscontrol show job <JOBID>

Typical Usage Pattern

# Day 1: Start workflow
ssh your_cluster
cd /scratch/$USER/vaspflow
bash run_workflow.sh --max-concurrent 20
# Note the job ID, then log out# Day 2: Check progress (from anywhere)
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if manager is still running
squeue -u $USER| grep vaspflow_manager
# Check workflow progress
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# View manager log
tail -f workflow_manager_*.out

Files

FilePurpose
prescreen.pyMatterSim pre-screening with batch processing
run_prescreen.shSubmit single-GPU pre-screening wrapper
submit_prescreen.shSLURM script for single-GPU pre-screening
submit_parallel_prescreen.shNEW: Parallel multi-GPU prescreening across nodes
merge_prescreen_batches.pyNEW: Merge parallel batch results into single file
plot_e_above_hull.pyVisualize pre-screening energy distribution
extract_stable_structs.pyExtract CIF files for stable structures
workflow_manager.pyVASP workflow with PyXtal symmetrization
run_workflow.shSubmit workflow wrapper (user-facing)
submit_workflow_manager.shSLURM script for workflow manager
workflow_status.pyStatus checking and reporting
reset_failed_jobs.pyReset failed jobs to retry (RELAX/SC/PARCHG)
compute_dft_e_hull.pyCompute DFT energy_above_hull + MatterSim comparison
run_dft_e_hull.shSubmit DFT hull wrapper (user-facing)
submit_dft_e_hull.shSLURM script for DFT hull calculation
compare_energy_methods.pyCompare MatterSim vs DFT energies (uses dft_stability_results.json)
run_compare_energy_method.shSubmit energy method comparison wrapper
submit_compare_energy_method.shSLURM script for energy method comparison
analyze.pyOrchestrates electride analysis (calls Electride.py)
analyze.shSLURM script for analysis job
Electride.pyBader analysis on ELFCAR + PARCHG files
submit_analysis.shSubmit analysis wrapper (user-facing)
filter_comb_db.pyNEW: Filter candidates with stricter volume criteria + PyXtal symmetry
extract_electride_struct.pyExtract CIF files from filtered database
generate_parchg_incars.pyHelper script to generate PARCHG INCARs from vasprun.xml-SC

Key Features:

  • Unified SPE workflow: SC-PARCHG-ELF run sequentially in one SLURM job (2 jobs per structure vs 8)
  • Simplified directory structure: Relax/ and SPE/ subdirectories (vs 7+ subdirectories)
  • Stage markers: SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE track progress within SPE job
  • Reduced SLURM overhead: 75% fewer jobs submitted to queue
  • Clean code separation: Python for VASP inputs, bash for workflow orchestration
  • Helper script for PARCHG: Standalone script generates PARCHG INCARs (band indices from vasprun.xml-SC)
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied during relaxation)
  • Batch processing: prescreen.py reuses MatterSimCalculator across structures (3-5× faster)
  • Parallel prescreening: submit_parallel_prescreen.sh splits across GPU nodes (linear speedup)
  • Complete GGA coverage: Uses legacy pymatgen.ext.matproj.MPRester for comprehensive GGA/GGA+U phases
  • Strict functional filtering: Only accepts entries with -GGA or -GGA+U suffix (excludes r2SCAN/SCAN)
  • Uncorrected energies: Uses raw DFT energies (no MP corrections) for accurate hull calculations
  • Optional pure-pbe: --pure-pbe flag to filter MP entries to pure GGA-PBE only (exclude PBE+U)
  • Single cache files: mp_mattersim.json and mp_vaspdft.json in VASP_JOBS/ directory
  • PyXtal symmetrization: Automatic structure symmetrization in both prescreening and VASP workflow
  • Two-step electride filtering: Initial analysis saves all data, stricter filtering for high-quality candidates
  • Fast symmetry analysis: PyXtal-based filtering (14× faster than AFLOW)
  • Query-able database: ase db commands for filtering candidates by stability, symmetry, or volumes
  • PDEntry for hulls: Uses PDEntry instead of ComputedEntry for accurate phase diagram analysis
  • reset_failed_jobs.py resets failed VASP jobs to retry them without data loss
  • Integrated hull validation: compute_dft_e_hull.py automatically validates pre-screening accuracy with plots and statistics
  • Energy method comparison: compare_energy_methods.py uses dft_stability_results.json as single source of truth for exact consistency
  • User-friendly wrapper scripts provide consistent interface across all stages

Best Practices

  1. Run pre-screening first with prescreen.py to save 40-60% of VASP computation
  2. Use parallel prescreening (submit_parallel_prescreen.sh) for large datasets (>500 compositions)
  3. Merge batch results with merge_prescreen_batches.py after all parallel jobs complete
  4. Optimize batch size based on GPU memory: 32 for A40/A100 (48GB), 16 for smaller GPUs
  5. Wait for pre-screening to complete before starting VASP workflow
  6. Check pre-screening results (prescreening_stability.json) to verify threshold is appropriate
  7. Inspect cache files (mp_mattersim.json, mp_vaspdft.json) to verify MP data quality
  8. Submit both jobs as SLURM jobs (required on most HPC systems)
  9. Monitor from login node using workflow_status.py instead of viewing logs constantly
  10. Set reasonable max_concurrent (10-20) to avoid queue congestion
  11. Monitor your quota on /scratch periodically (cache files are now much smaller: ~1-5 MB total)
  12. Check failed jobs early to catch systematic issues
  13. Start small (test with 2-3 structures first using --max-compositions 2 --max-structures 2)
  14. Trust PyXtal symmetrization - structures are automatically symmetrized for consistency

Common Workflows

Production Run (Full Scale)

# Step 1: Pre-screening# Option A: Single GPU (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--device cuda \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets >500 compositions)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400
# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Auto-splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor with: squeue -u $USER | grep prescreen# Wait for completion, check and visualize results
cat VASP_JOBS/prescreening_stability.json | jq '.summary'
cat VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'
jq '.results[] | select(.passed_prescreening == true) | {structure_id, energy_above_hull}' VASP_JOBS/prescreening_stability.json
python3 plot_e_above_hull.py --bins 100
# (Optional) Extract stable structures for inspection
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# Step 2: VASP workflow (structures automatically symmetrized with PyXtal)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0 \
--check-interval 120
# Step 3: Analyze electride candidates
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# Step 4: Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# Step 5: Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Step 6: Query and explore
ase db electride_candidates.db
ase db electride_candidates.db 'e_above_hull<0.05' -s space_group_number-

Resume After Interruption

# Check if still running
squeue -u $USER| grep vaspflow_manager
# If stopped, restart - database persists
bash run_workflow.sh --max-concurrent 20

Integration with MatterGen

# 1. Generate structures with MatterGencd~/mattergen_test/ternary_electride
bash generate_ternary_csp.sh
# 2. Transfer to HPC scratchcd /scratch/$USER
cp -r ~/mattergen_test/results/ternary_csp_electrides mattergen_results/
# 3. Run pre-screening (as SLURM job)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Wait for pre-screening to complete
squeue -u $USER| grep prescreen
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 3b. Visualize and extract stable structures (optional)
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 4. Start VASP workflow (as SLURM job)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20
# 5. Monitor and analyze
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# 6. Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# 7. Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# 8. Query candidates
ase db electride_candidates.db 'e_above_hull<0.05'

Credits & References

Credits:

Tools & Libraries:

Key Paper:

@article{zhuComputationalDiscoveryInorganic2019,
title = {Computational {{Discovery}} of {{Inorganic Electrides}} from an {{Automated Screening}}},
author = {Zhu, Qiang and Frolov, Timofey and Choudhary, Kamal},
year = 2019,
month = nov,
journal = {Matter},
volume = {1},
number = {5},
pages = {1293--1303},
issn = {2590-2385},
doi = {10.1016/j.matt.2019.06.017},
}
@misc{tao2026acceleratedinorganicelectridesdiscovery,
title={Accelerated Inorganic Electrides Discovery by Generative Models and Hierarchical Screening}, author={Shuo Tao and Qiang Zhu},
year={2026},
eprint={2601.21077},
archivePrefix={arXiv},
primaryClass={cond-mat.mtrl-sci},
url={https://arxiv.org/abs/2601.21077}, }

About

DFT-HT Workflow for screening inorganic electrides

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

ElectrideFlow - High-Throughput Inorganic Electride Discovery Workflow Accelerated by Generative Models and Hierarchical Prescreening

A four-stage intelligent workflow for high-throughput inorganic electride discovery on HPC clusters:

  1. Chemical Exploration - Generative AI models (MatterGen) explore composition space targeting electride-favorable chemistries
  2. Stability Screening - MatterSim (MLP) pre-screening filters structures by energy above hull before expensive DFT calculations
  3. Electride Identification - Coarse DFT relaxation with ELF & PARCHG topological analysis to identify electride candidates
  4. Refinement - Tight DFT relaxation with refined convex hull analysis for final candidate validation

Table of Contents


Features

MatterSim pre-screening - filter structures by energy_above_hull before VASP (saves 40-60% computation)
Batch processing - reuses MatterSimCalculator across structures for GPU memory efficiency
Parallel prescreening - split prescreening across multiple GPU nodes for faster throughput
Stable phases only - queries only on-hull MP phases for accurate, fast convex hull analysis
Smart caching - single global cache files (mp_mattersim.json, mp_vaspdft.json) handle overlapping systems
PyXtal symmetrization - automatic structure symmetrization for better VASP convergence
Unified SPE workflow - SC-PARCHG-ELF in single job (75% fewer SLURM jobs)
Batch submission - submit n structures at a time, auto-submit more as jobs complete
Dynamic monitoring - check status and submit new jobs automatically
Local JSON database - no network dependencies, works on HPC
Smart workflow - Pre-screen → Relax → SPE (SC + PARCHG + ELF sequential)
PARCHG analysis - band-edge charge density for accurate electride identification
Two-step filtering - initial analysis saves all, stricter filtering for candidates
Fast symmetry - PyXtal-based (14× faster than AFLOW)
Query-able database - ase db commands for candidate exploration
Pymatgen input generation - INCAR, POSCAR, POTCAR, KPOINTS
Bader analysis - identify electride candidates with topological analysis
Interrupt-safe - resume from any interruption
HPC-friendly - workflow manager runs as SLURM job


Quick Start

1. Setup Environment

# On HPC login nodecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# Copy files from your local machine:# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow orchestration# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Monitor workflow progress# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# Load CUDA runtime (check your HPC's available versions, need >= 11.8)
module load cuda/11.8
# Create conda environment
conda create -n mattersim python=3.10
conda activate mattersim
# Install PyTorch with matching CUDA version FIRST# (adjust cu118 to match your loaded CUDA module)
pip install torch==2.5.1+cu118 torchvision==0.20.1+cu118 torchaudio==2.5.1+cu118 \
--index-url https://download.pytorch.org/whl/cu118
pip install torch_scatter==2.1.2+pt25cu118 torch_sparse==0.6.18+pt25cu118 \
torch_cluster==1.6.3+pt25cu118 torch_spline_conv==1.2.2+pt25cu118 \
-f https://data.pyg.org/whl/torch-2.5.1+cu118.html
pip install torch-geometric==2.7.0 pytorch-lightning==2.0.6
# Install pymatgen/mp-api (pinned versions for MP API compatibility)
pip install pymatgen==2024.10.29 mp-api==0.43.0 monty==2024.7.30 emmet-core==0.84.10
# Install other dependencies
pip install numpy>=2.0 ase==3.23.0 pyxtal==1.1.1
# Install MatterSim last (--no-deps to avoid overriding torch versions)
pip install mattersim --no-deps
# Then install any missing mattersim deps that don't conflict:
pip install torch-ema torch-runstats torchmetrics
# Set environment variables in ~/.bashrcecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc

2. Pre-screening with MatterSim (NEW Step)

# Option A: Single GPU job (for small datasets)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--device cuda \
--compositions-per-job 400
# Optional: Add --pure-pbe flag to filter MP entries to pure GGA-PBE only# (default is mixed PBE/PBE+U which is recommended for best accuracy)# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Automatically splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# When done, check results
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# View cache files (single global files with chemsys field)
ls -lh ./VASP_JOBS/mp_mattersim.json
cat ./VASP_JOBS/mp_mattersim.json | jq '.[0]'# (Optional) Visualize results and extract CIF files
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

3. VASP Workflow (Run After Pre-screening)

# Submit VASP workflow manager (processes structures that passed pre-screening)cd /scratch/$USER/vaspflow
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Check job status
squeue -u $USER
tail -f workflow_manager_<JOBID>.out

4. Monitor Progress

cd /scratch/$USER/vaspflow
conda activate mattersim
# Check workflow manager job
squeue -u $USER# View workflow manager log
tail -f workflow_manager_<JOBID>.out
# Overall workflow status
python workflow_status.py ./VASP_JOBS/workflow.json
# Composition breakdown
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# Running VASP jobs
python workflow_status.py ./VASP_JOBS/workflow.json --running
# Failed structures
python workflow_status.py ./VASP_JOBS/workflow.json --failed

5. Analyze Results

# Submit electride analysis as SLURM job
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# When complete, view all analyzed structures
cat electride_analysis.csv
# Filter with stricter criteria to get high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# View filtered candidates
cat electride_candidates.csv
# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Query database for specific criteria
ase db electride_candidates.db 'e_above_hull<0.05'

Complete Setup Guide

Initial Setup (One-time)

# 1. SSH to HPC
ssh your_cluster
# 2. Create conda environment with all dependencies
conda create -n mattersim python=3.10
conda activate mattersim
conda install -c conda-forge pymatgen mp-api
pip install mattersim ase
# 3. Setup workspacecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# 4. Upload workflow scripts from your local machine# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Status monitoring# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# 5. Make scripts executable
chmod +x *.py *.sh
# 6. Set environment variablesecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc
# 7. Verify setup
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
echo"MP API Key: $MP_API_KEY"

Starting a Workflow

# 1. SSH to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# 2. Run pre-screening first (MatterSim + MP)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# Wait for pre-screening to complete (~1-2 hours for 100 structures)# Check results:
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 2b. (Optional) Visualize and extract stable structures
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 3. Submit VASP workflow manager (processes passing structures)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20 \
--max-structures 0
# 4. Monitor (optional)
squeue -u $USER# Check job status
tail -f workflow_manager_*.out # View log# You can now safely log out - workflow runs as SLURM job!

Resuming After Interruption

# SSH back to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if workflow manager is still running
squeue -u $USER| grep vaspflow_manager
# If not running, resubmit (database persists!)
bash run_workflow.sh --max-concurrent 20
# It automatically resumes from saved state in workflow.json

Workflow Overview

Architecture

MatterGen Structures
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 1: Pre-screening (prescreen.py + MatterSim) │
│ - SLURM job on compute node │
│ - Relax structures with MatterSim ML potential │
│ - Query MP for competing phases (cached per chemical system)│
│ - Compute energy_above_hull │
│ - Output: prescreening_stability.json │
│ - Filter: only E_hull < 0.1 eV/atom proceed to VASP │
└──────────────────────────────────────────────────────────────┘
↓
prescreening_stability.json
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 2: VASP Workflow (workflow_manager.py) │
│ - SLURM job on compute node │
│ - Initialize workflow database (JSON) │
│ - Batch submission loop: │
│ * Submit up to max_concurrent VASP jobs │
│ * Each structure: Relax → SC → PARCHG* → ELF (sequential)│
│ (* PARCHG only for semiconductors, band gap > 0.01 eV) │
│ * Monitor job completion every 60s │
│ * Submit new structures as slots free up │
└──────────────────────────────────────────────────────────────┘
↓
Analyze ELF + PARCHG Results (Bader analysis)
↓
Identify Electride Candidates

Job Chain Per Structure

  1. Pre-screening (MatterSim): Quick stability check → energy_above_hull
  2. Relax (VASP): Optimize geometry → CONTCAR
  3. SC (Self-Consistent): Accurate electronic structure → CHGCAR, WAVECAR, vasprun.xml
  4. PARCHG (all materials): Band-decomposed charge density → PARCHG-band0, PARCHG-band1, PARCHG-e0025, PARCHG-e05, PARCHG-e10
  5. ELF: Calculate electron localization → ELFCAR (PARCHG files copied here for analysis)

Directory Structure

/scratch/$USER/VASP_JOBS/
├── Li10B1N3/
│ ├── Li10B1N3_s001/
│ │ ├── Relax/
│ │ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ │ ├── job.sh
│ │ │ ├── CONTCAR (after completion)
│ │ │ ├── VASP_DONE (or VASP_FAILED)
│ │ │ └── vasp_*.out/err
│ │ └── SPE/ ← Unified SC-PARCHG-ELF directory
│ │ ├── job.sh ← Single SLURM job for all stages
│ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ ├── generate_parchg_incars.py ← Helper script (copied by workflow)
│ │ ├── SC_DONE, PARCHG_DONE ← Stage markers
│ │ ├── VASP_DONE (or VASP_FAILED) ← Final completion marker
│ │ ├── INCAR-SC, OSZICAR-SC, vasprun.xml-SC ← SC outputs
│ │ ├── INCAR-PARCHG-e0025, INCAR-PARCHG-e05, INCAR-PARCHG-e10
│ │ ├── INCAR-PARCHG-band0, INCAR-PARCHG-band1
│ │ ├── PARCHG.tar.gz ← Compressed PARCHG files
│ │ ├── INCAR-ELF
│ │ ├── ELFCAR ← ELF output
│ │ ├── ELF_DONE ← ELF stage marker
│ │ └── vasp_*.out/err
│ └── Li10B1N3_s002/
├── workflow.json # Job tracking database
├── prescreening_stability.json ← Pre-screening results
├── mp_mattersim.json ← Cached MP stable phases (MatterSim energies)
├── mp_vaspdft.json ← Cached MP stable phases (DFT energies)
└── electride_candidates.json # Analysis results

Workflow States

Each structure progresses through these states in workflow_manager.py:

PENDING (structure passed pre-screening, ready for VASP)
↓
RELAX_RUNNING → RELAX_DONE → SC_RUNNING → PARCHG_RUNNING → ELF_RUNNING → ELF_DONE
↓ ↓ ↓ ↓ ↓ ↓
RELAX_FAILED (skip) SC_FAILED PARCHG_FAILED ELF_FAILED (success)
Note: SC_RUNNING, PARCHG_RUNNING, and ELF_RUNNING are all part of one SPE job
State transitions happen automatically as stage markers are detected

Note: Pre-screening (MatterSim + MP hull analysis) is done separately by prescreen.py. Only structures that pass pre-screening (E_hull < threshold) are loaded into workflow_manager.py.

Key behaviors:

  • Only structures that passed pre-screening are processed
  • Reduced SLURM jobs: 2 jobs per structure (1 Relax + 1 SPE) instead of 8 jobs
  • SPE job runs sequentially: SC -> PARCHG (5 energy windows) -> ELF in one script
  • Stage markers: SC_DONE, PARCHG_DONE, VASP_DONE track progress within SPE job
  • State transitions: Workflow manager detects markers and transitions states automatically
  • PARCHG for ALL materials: Following HT-electride methodology
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied)
  • Workflow manager automatically submits next structure when slots free up
  • Failed jobs don't block other structures
  • Max concurrent limit applies to total running structures

SPE Workflow Architecture

The unified SPE (SC-PARCHG-ELF) workflow uses a clean separation of concerns:

Python (workflow_manager.py) handles:

  • INCAR/POSCAR/POTCAR/KPOINTS for Relax, SC, ELF jobs
  • Structure loading from CIF files and symmetrization
  • Database state tracking and job orchestration
  • Directory structure creation

Helper script (generate_parchg_incars.py) handles:

  • PARCHG INCAR generation (requires parsing vasprun.xml-SC)
  • Band index calculation from NELECT and SOC parameters
  • FFT grid extraction (NGXF, NGYF, NGZF)
  • Called from bash after SC completes

Bash (job.sh in SPE/) handles:

  • Sequential execution: SC → PARCHG (5 types) → ELF
  • File copying between stages (CHGCAR-SC, WAVECAR-SC reused)
  • PARCHG output renaming (PARCHG → PARCHG-e0025, etc.)
  • PARCHG compression (PARCHG-* → PARCHG.tar.gz) to save disk space
  • Cleanup between stages to prevent VASP issues
  • Stage marker creation (SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE)

Why this design:

  • PARCHG is the ONLY calculation requiring runtime VASP output parsing
  • Keeps Python code IDE-friendly (no embedded heredocs)
  • Helper script is testable standalone
  • Other INCARs are straightforward pymatgen calls (no external scripts needed)

Monitoring

Option 1: Workflow Status Tool (Recommended)

# Overall summary
python workflow_status.py ./VASP_JOBS/workflow.json

Shows:

  • Total structures
  • Status breakdown (PENDING, RELAX_RUNNING, SC_RUNNING, etc.)
  • Currently running count
  • Completion percentage

Additional views:

# Running jobs with SLURM job IDs
python workflow_status.py workflow.json --running
# Failed structures (for debugging)
python workflow_status.py workflow.json --failed
# Composition-level summary
python workflow_status.py workflow.json --compositions
# Recently completed structures
python workflow_status.py workflow.json --completed --limit 20
# Filter by specific state
python workflow_status.py workflow.json --details --state SC_RUNNING

Option 2: Reattach to Tmux

# See live workflow output
tmux attach -t vaspflow
# View, then detach: Ctrl+B, then D

Option 3: Check SLURM Queue

# Check running jobs
squeue -u $USER# Check job history
sacct -S $(date --date="7 days ago" -I) -u $USER# Detailed job info
scontrol show job <JOBID>

Option 4: Manual Inspection

# View database directly
cat ./VASP_JOBS/workflow.json | jq '.structures | to_entries | map({id: .key, state: .value.state})'# Check specific job directorycd ./VASP_JOBS/Li10B1N3/Li10B1N3_s001/Relax
ls -lh
tail vasp_*.out
tail OSZICAR

Analyzing Results for Electride Candidates

After ELF calculations complete, analyze structures for electride characteristics using Bader topological analysis on both ELFCAR and PARCHG files.

New in v2.0: Incremental analysis with MatterSim e_above_hull integration, PyXtal database storage, and stricter candidate filtering.

Step 1: Initial Analysis (All Structures)

Recommended: Run analysis as a SLURM job (not on login node):

# Submit analysis job with defaults
bash submit_analysis.sh
# Custom settings
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# View results when complete
cat electride_analysis.csv

Output:

  • electride_analysis.csv - All analyzed structures with interstitial volumes
  • electride_data.db - PyXtal database with all structures

Step 2: Filter High-Quality Candidates

Apply stricter volume thresholds to identify high-quality electride candidates:

# Filter with default thresholds (20 ų)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# Custom thresholds (stricter)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 25 \
--min-band 25

Filtering Criteria:

  • max(e0025, e05, e10) >= min-energy (default: 20 ų)
  • max(band0, band1) >= min-band (default: 20 ų)
  • Removes duplicate structures
  • Adds PyXtal symmetry information (space groups)

Output:

  • electride_candidates.db - Filtered high-quality candidates with symmetry
  • electride_candidates.csv - CSV table for quick viewing

Step 3: Extract CIF Files

Extract CIF files for the filtered candidates:

# Extract from filtered database
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Output: electride_CIF/*.cif - One CIF file per candidate

Step 4: Query Database

Use ase db to query and filter candidates:

# View all candidates
ase db electride_candidates.db
# Sort by space group (high symmetry first)
ase db electride_candidates.db \
formula,space_group_number,e_above_hull \
-s space_group_number-
# Filter by stability (< 50 meV/atom)
ase db electride_candidates.db 'e_above_hull<0.05'# Show interstitial volumes
ase db electride_candidates.db \
formula,e0025,e05,e10,band0,band1,e_above_hull
# Cubic structures (space group >= 195)
ase db electride_candidates.db 'space_group_number>=195'# High interstitial volume (e0025 > 50 ų)
ase db electride_candidates.db 'e0025>50'

What the Analysis Does

Initial Analysis (analyze.py):

  1. Reads ELFCAR - electron localization function from VASP SPE directory
  2. Extracts PARCHG files from PARCHG.tar.gz (5 types):
    • PARCHG-band0: Valence band maximum (VBM)
    • PARCHG-band1: Second highest occupied band (VBM-1)
    • PARCHG-e0025: Energy window [-0.025, 0.025] eV around Fermi level
    • PARCHG-e05: Energy window [-0.5, 0.025] eV
    • PARCHG-e10: Energy window [-1.0, 0.025] eV
  3. Runs Bader analysis on ELFCAR and each PARCHG file
  4. Filters interstitial electrons - sites far from atoms with high localization
  5. Reports volumes of interstitial electron density (ų) for each type
  6. Adds stability data - reads e_above_hull from prescreening_stability.json
  7. Extracts spacegroup - from CONTCAR using PyXtal (adaptive tolerance)
  8. Saves to database - stores all structures in electride_data.db

Filtering (filter_comb_db.py):

  1. Applies volume thresholds - only keeps structures with substantial interstitial volumes
  2. Symmetrizes structures - uses PyXtal with adaptive tolerance (coarse→fine)
  3. Removes duplicates - identifies and filters redundant structures
  4. Adds space group info - from PyXtal symmetry analysis
  5. Creates unified database - electride_candidates.db with structures + volumes
  6. Exports CSV - electride_candidates.csv for quick viewing

Key Features (v2.0)

Incremental Analysis:

  • Automatically skips already-analyzed structures from CSV and database
  • Run repeatedly as new ELF calculations complete without re-processing
  • Perfect for monitoring ongoing workflows

Enhanced Electride Criteria:

  • Old criteria: ANY of (e0025 > 0 OR e05 > 0 OR e10 > 0 OR band0 > 0)
  • New criteria: ALL of (e0025 > 0 AND e05 > 0 AND e10 > 0 AND band0 > 0)
  • More stringent to reduce false positives

DFT Integration:

  • Reads DFT energy_above_hull from compute_dft_e_hull.py output
  • Results sorted by stability (lowest e_above_hull first)
  • Most stable electride candidates rise to the top

PyXtal Database:

  • Saves all analyzed structures to electride_data.db
  • Adaptive symmetrization (tolerances: 1e-5 to 0.5)
  • P1 fallback ensures 100% save success
  • Query-able for advanced analysis

Analysis Parameters

analyze.py:

  • --threshold: Minimum ELF value for electride detection (default: 0.6)
  • --bader-exe: Path to Bader executable (default: bader in PATH)
  • --output: Output CSV file name (default: electride_analysis.csv)
  • --pyxtal-db: PyXtal database file (default: electride_data.db)
  • --prescreening: MatterSim stability JSON (default: ./VASP_JOBS/prescreening_stability.json)
  • --workers: Number of parallel workers (default: CPU count)

filter_comb_db.py:

  • --min-energy: Minimum for max(e0025, e05, e10) in ų (default: 20)
  • --min-band: Minimum for max(band0, band1) in ų (default: 20)
  • --output: Output database (default: electride_candidates.db)
  • --output-csv: Output CSV (default: electride_candidates.csv)

Understanding Results

Initial Analysis (electride_analysis.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045
Li10B1N4_s003,Li10B1N4,0.00,0.00,0.00,5.28,0.00,12,0.068

Columns:

  • formula: Structure ID
  • composition: Chemical formula
  • e0025, e05, e10: Interstitial volumes (ų) from energy windows
  • band0, band1: Interstitial volumes (ų) from band-specific charges
  • spacegroup: PyXtal space group (1 = P1 fallback)
  • e_above_hull: MatterSim energy above hull (eV/atom)

Electride Criteria:

  • (e0025 > 0 OR e05 > 0) AND (e10 > 0 OR band0 > 0)

Filtered Candidates (electride_candidates.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045

Additional Filtering:

  • max(e0025, e05, e10) >= 20 ų (substantial energy window volume)
  • max(band0, band1) >= 20 ų (substantial band-specific volume)
  • Duplicates removed
  • Space group from PyXtal symmetry analysis

Interpreting volumes (in ų):

  • > 20: High-quality electride (passes filtering)
  • 0-20: Weak electride (filtered out by default)
  • High across multiple columns: Strong, robust electride character

Example interpretation:

  • Li10B1N4_s001: High-quality electride (all volumes > 20 ų, stable)
  • Li10B1N4_s002: Moderate electride (volumes > 12 ų, borderline)
  • Li10B1N4_s003: Not electride (very low volumes)

Sorting:

  • Both CSVs sorted by e_above_hull (low → high)
  • Most thermodynamically stable candidates appear first

Console output during analysis:

Total ELF_DONE: 100
Semiconductors (with PARCHG): 15
Metals (ELFCAR only): 85
(All structures analyzed with PARCHG in SPE workflow)
Analyzing: Li10B1N4_s001 (VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE)
Spacegroup: 166
*** ELECTRIDE CANDIDATE *** (e0025=32.62, e05=31.82, e10=31.31, band0=35.11, band1=0.00)
Analyzing: Li10B1N4_s003 (VASP_JOBS/Li10B1N4/Li10B1N4_s003/SPE)
Spacegroup: 139
Not electride (e0025=0.00, e05=0.00, e10=0.00, band0=5.28, band1=0.00)

Filter output:

======================================================================
Filtering Electride Database with Stricter Criteria
======================================================================
Criteria:
max(e0025, e05, e10) >= 20.0 ų
max(band0, band1) >= 20.0 ų
Processing structures...
Added 100 structures...
Using P1 fallback for Ba8S7_s024
Added 200 structures...
Filtering Summary:
Input structures: 6134
Filtered out (below thresholds): 4512
Duplicates removed: 89
Failed to process: 0
Added to output database: 1533

Incremental Analysis Workflow

# Day 1: 50 ELF calculations done
bash submit_analysis.sh
# Output: 50 structures analyzed# → electride_analysis.csv (50 structures)# → electride_data.db (50 structures)# Filter to get high-quality candidates
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 25 high-quality)# electride_candidates.csv# Day 2: 30 more ELF calculations done (total 80)
bash submit_analysis.sh
# Output: Only 30 new analyzed (skips existing 50)# → electride_analysis.csv updated (80 total, re-sorted)# → electride_data.db updated (80 total)# Re-filter with updated data
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 40 high-quality)# Day 3: 20 more ELF calculations done (total 100)
bash submit_analysis.sh
# Output: Only 20 new analyzed# → Final electride_analysis.csv (100 structures)# Final filtering
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: Final electride_candidates.db (e.g., 50 high-quality)# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Benefits:

  • Incremental analysis saves time (only analyzes new structures)
  • Filtering is fast (~2 min) and can be adjusted without re-running Bader
  • Database is query-able at any stage

Direct Analysis (Advanced)

The analysis uses Electride.py internally via analyze.py. For manual testing:

# Test on single structure (SPE workflow)cd VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE
python3 ../../../../Electride.py . --bader-exe ~/apps/Bader/bader
# Run full analysis with all options
python3 analyze.py \
--db VASP_JOBS/workflow.json \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv \
--pyxtal-db electride_data.db \
--prescreening VASP_JOBS/prescreening_stability.json \
--workers 32
# Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20

Requirements:

  • ELFCAR file (generated by VASP with LELF=True in SPE/)
  • PARCHG.tar.gz (5 files compressed, automatically extracted during analysis)
  • Bader executable (download from: https://theory.cm.utexas.edu/henkelman/code/bader/)
  • (Optional) prescreening_stability.json for MatterSim e_above_hull values

Output Files

Initial Analysis:

  1. electride_analysis.csv: All analyzed structures with volumes
  2. electride_data.db: PyXtal database with all structures
  3. electride_analysis_detailed.log: Full console output

Filtered Candidates:

  1. electride_candidates.csv: High-quality candidates (CSV table)
  2. electride_candidates.db: PyXtal database with filtered structures + volumes
  3. electride_CIF/: Directory with CIF files for candidates

Performance

Analysis (analyze.py):

  • Incremental mode: Only analyzes new structures (minutes for 30 new structures)
  • Full analysis: ~5-10 minutes per structure (PARCHG extraction + Bader analysis)
  • Database saves: ~1 second per structure (with adaptive tolerance)
  • Parallel processing: Scales with CPU cores (32 cores recommended)

Filtering (filter_comb_db.py):

  • Time: ~2 minutes for 6000 structures
  • PyXtal symmetry: ~0.02 sec per structure (vs AFLOW: ~0.45 sec)
  • Speedup: 14× faster than AFLOW-based workflow
  • Duplicate removal: Automatic during processing

DFT Energy Above Hull Calculation

After VASP relaxations complete, compute DFT-level thermodynamic stability using your VASP energies combined with Materials Project DFT energies for competing phases.

Energy Method Comparison

Compare energies between different calculation methods to validate pre-screening accuracy and diagnose any systematic biases:

# Run comparison (requires dft_stability_results.json)
bash run_compare_energy_method.sh \
--vasp-jobs ./VASP_JOBS \
--outlier-threshold 0.5
# Monitor job
squeue -u $USER| grep compare_energy
tail -f compare_energy_method_*.out
# Results will be in: VASP_JOBS/energy_method_comparison.json# Plots: mp_phases_comparison_*.png, generated_structures_comparison_*.png

What it compares:

  1. MP On-Hull Phases: MatterSim energies vs MP raw DFT energies
  2. Generated Structures: MatterSim energies vs VASP-DFT energies

Important: The generated structures comparison now uses dft_stability_results.json as the single source of truth for VASP energies. This ensures exact consistency with hull_comparison plots (same structures, same outlier filtering).

Key metrics:

  • Pearson correlation between methods
  • Mean Absolute Error (MAE)
  • Systematic bias detection
  • Helps diagnose non-linear hull behavior

Usage

# Submit DFT hull calculation (after VASP relaxations complete)
bash run_dft_e_hull.sh \
--vasp-jobs ./VASP_JOBS \
--output dft_stability_results.json \
--prescreen-results ./VASP_JOBS/prescreening_stability.json
# Monitor job
squeue -u $USER| grep dft_e_hull
tail -f dft_e_hull_*.out
# Hull comparison (MatterSim vs DFT) is automatically generated# if --prescreen-results is provided to compute_dft_e_hull.py# Results will be in: VASP_JOBS/hull_comparison.json# Plots: hull_comparison_scatter.png, hull_comparison_residuals.png

What It Does

  1. Scans for completed VASP relaxations (RELAX_DONE or later states)
  2. Extracts VASP energies from vasprun.xml
  3. Queries MP for stable phases only (is_stable=True) - much faster than querying all phases
  4. Uses single cache file (mp_vaspdft.json) with automatic subsystem handling
  5. Computes DFT energy_above_hull for each structure using PDEntry
  6. Outputsdft_stability_results.json with decomposition products

Output Format

{
"summary": {
"total_structures": 100,
"processed_successfully": 95,
"failed": 5,
"energy_reference": "DFT uncorrected (VASP-PBE + MP stable phases only)",
"mp_phase_selection": "stable_only (is_stable=True)",
"mp_functional_filter": "mixed_pbe_pbeU"
},
"results": [
{
"structure_id": "Li10B1N4_s001",
"composition": "Li10B1N4",
"chemsys": "B-Li-N",
"vasp_energy_per_atom": -3.45678,
"dft_energy_above_hull": 0.023,
"decomposition_products": "Li3N (0.714) + BN (0.286)",
"num_mp_stable_phases": 18,
"error": null
}
]
}

Validation: MatterSim vs DFT Hull Comparison

The compute_dft_e_hull.py script automatically validates pre-screening accuracy by comparing MatterSim vs DFT hull values when --prescreen-results is provided:

Statistical metrics:

  • Pearson correlation (how well MatterSim predicts DFT)
  • Mean Absolute Error (MAE)
  • Root Mean Square Error (RMSE)

Pre-screening performance:

  • True Positives: Correctly passed (stable in both)
  • False Positives: Incorrectly passed (unstable in DFT, wasted VASP)
  • True Negatives: Correctly filtered (unstable in both)
  • False Negatives: Incorrectly filtered (stable in DFT, missed!)
  • Precision, Recall, F1 Score
  • Computational savings (% VASP avoided)

Output: hull_comparison.json with detailed analysis

When to Use

  • After some VASP relaxations complete: Validate pre-screening accuracy early
  • Before publication: Get accurate DFT stability data
  • To identify outliers: Find structures that were incorrectly filtered/passed

Performance

  • Time: ~1-2 hours for 100 structures (mostly MP API queries)
  • Resources: 8 CPUs, 32GB RAM (for large systems)
  • Caching: Uses MP IDs from pre-screening cache to minimize API calls

Troubleshooting

Workflow Manager Not Running

Symptom: Jobs complete but database still shows RUNNING state

Check if manager job is running:

squeue -u $USER| grep vaspflow_manager

Solution: Restart workflow manager if stopped

bash run_workflow.sh --max-concurrent 10
# It will detect completed jobs and update states

Jobs Not Progressing

Check:

# Check workflow manager job
squeue -u $USER| grep vaspflow_manager
tail -f workflow_manager_*.out
# See what's completed
find ./VASP_JOBS -name "VASP_DONE"| wc -l
find ./VASP_JOBS -name "VASP_FAILED"| wc -l
# Check VASP jobs in queue
squeue -u $USER# Check database state
python workflow_status.py ./VASP_JOBS/workflow.json

Fix: Restart workflow manager if it stopped

bash run_workflow.sh --max-concurrent 10

Failed Jobs

# List all failures
python workflow_status.py workflow.json --failed
# Investigate specific failurecd ./VASP_JOBS/Li10B1N3/Li10B1N3_s003/Relax
tail -50 vasp_*.err
tail -50 OSZICAR
grep -i "error\|killed\|fail" vasp_*.out

Common failure causes:

  • Walltime limit hit (24 hours default)
  • Convergence issues (check OSZICAR)
  • Memory issues (check vasp_*.err)
  • POTCAR problems (check first few lines of vasp_*.out)

Resetting Failed Jobs for Retry

Use reset_failed_jobs.py to reset failed structures and retry them:

# Step 1: List all failed structures to understand what went wrong
python3 reset_failed_jobs.py --list
# Output shows failures grouped by stage:# RELAX_FAILED: 72 structures# SC_FAILED: 4 structures# PARCHG_FAILED: 4 structures# Step 2: Dry run to preview changes (recommended)
python3 reset_failed_jobs.py --dry-run --clean
# Step 3: Reset all failed jobs
python3 reset_failed_jobs.py --clean
# OR reset specific stage only
python3 reset_failed_jobs.py --stage RELAX --clean
python3 reset_failed_jobs.py --stage SC --clean
python3 reset_failed_jobs.py --stage PARCHG --clean
# Step 4: Resume workflow to retry
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10

What it does:

  • RELAX_FAILEDPENDING (retry from scratch)
  • SC_FAILEDRELAX_DONE (retry SC using existing relaxed structure)
  • PARCHG_FAILEDSC_DONE (retry PARCHG using existing SC results)
  • --clean flag removes VASP_FAILED markers for clean restart
  • Creates automatic backup: workflow.json.bak

Important: Investigate failure causes before blindly retrying. Some structures may have fundamental issues (bad geometry, unconverged, etc.) and will fail repeatedly.

POTCAR Not Found

# Check environmentecho$PMG_VASP_PSP_DIR# Verify structure
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
# Set if neededexport PMG_VASP_PSP_DIR=$HOME/apps/PBE64
# Add to ~/.bashrc to persist

Workflow Manager Job Issues

# Check if manager job is running
squeue -u $USER| grep vaspflow_manager
# View manager log
tail -100 workflow_manager_*.out
# Cancel stuck manager job
scancel <JOBID># Restart (database persists!)
bash run_workflow.sh --max-concurrent 10

Jobs Stuck in SLURM Queue

# Check job status
squeue -u $USER -o "%.18i %.9P %.30j %.8T %.10M %.6D %R"# Check why pending
squeue -u $USER -j <JOBID> --start
# Cancel stuck job if needed
scancel <JOBID># Workflow will mark it as failed on next check

Database Corruption

# Backup database
cp workflow.json workflow.json.backup
# Reinitialize (keeps existing directories)
python workflow_manager.py --init-only \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS
# Manually merge completed jobs from backup if needed

Parallel Pre-screening Results Missing

Symptom: After running submit_parallel_prescreen.sh, the prescreening_stability.json file is empty or only contains results from one batch.

Cause: Multiple parallel jobs writing to the same file cause race conditions and data loss.

Solution:

  1. Each batch processes a different subset of compositions using --start-composition (batch 0: comps 0-399, batch 1: 400-799, etc.)
  2. Each batch writes to its own file (prescreening_stability_batch0.json, etc.)
  3. After all jobs complete, merge them with merge_prescreen_batches.py:
# Check that all batch jobs completed
squeue -u $USER| grep prescreen # Should be empty# List batch result files
ls ./VASP_JOBS/prescreening_stability_batch*.json
ls ./VASP_JOBS/prescreening_structures_batch*.db
ls ./VASP_JOBS/mp_mattersim.json # Shared cache (not batch-specific)# Merge all batch results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# OR skip database merge (faster, JSON only)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS --skip-database
# Verify merged results
cat ./VASP_JOBS/prescreening_stability.json | jq '.metadata.total_structures'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Check shared MP cache
ls -lh ./VASP_JOBS/prescreening_structures.db # Check database exists

Prevention: Always run merge_prescreen_batches.py after parallel prescreening jobs complete.


Configuration

Key Parameters

Pre-screening (prescreen.py):

# Single GPU job
python prescreen.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0 \ # Max structures per composition
--batch-size 32 \ # Structures per batch (calculator reuse)
--mp-api-key YOUR_KEY \ # Materials Project API key
--hull-threshold 0.05 \ # E_hull threshold (eV/atom)
--device cuda \ # MatterSim device: cpu or cuda
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Automatically splits compositions across GPU nodes

VASP Workflow (workflow_manager.py):

python workflow_manager.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \ # Max structures running simultaneously
--max-compositions 20 \ # Limit number of compositions (optional)
--max-structures 0 \ # Max structures per composition
--check-interval 60 # Status check interval (seconds)

Recommendations:

  • Pre-screening:
    • --batch-size: 32 for A40/A100 GPUs (48GB VRAM), reduce to 16 for smaller GPUs
    • --hull-threshold: 0.1 eV/atom filters most unstable structures, use 0.05 for stricter filtering
    • --device: Use cuda for GPU acceleration (5-10× faster than CPU)
    • --mp-api-key: Get your free API key at https://next-gen.materialsproject.org/api
    • --pure-pbe: OPTIONAL flag to exclude PBE+U (recommended to OMIT for best accuracy)
      • Default (no flag): Mixed PBE/PBE+U (matches MP phase diagram methodology)
      • With flag: Pure GGA-PBE only (may reduce accuracy for transition metal systems)
    • MP API: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • Large datasets: Use submit_parallel_prescreen.sh to split across multiple GPUs
    • GPU memory: Set export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True in SLURM script
  • VASP Workflow:
  • --max-concurrent: 10-20 for typical HPC cluster
  • --check-interval: 60s is good balance
  • --max-compositions: Omit to process all
    • PyXtal: Structures automatically symmetrized for better convergence

SLURM Settings

Edit create_slurm_script() in workflow_manager.py (lines 163-176):

script=f"""#!/bin/bash#SBATCH --partition=Apus # Change partition#SBATCH --ntasks=32 # Change cores#SBATCH --time=1-00:00:00 # Change walltime (1 day)#SBATCH --mem=64G # Change memoery#SBATCH --output={job_dir}/vasp_%j.out#SBATCH --error={job_dir}/vasp_%j.err

VASP Input Settings

Edit create_vasp_inputs() in workflow_manager.py (lines 129-161):

Relax (line 135-142):

vis=MPRelaxSet(structure, user_incar_settings={
'EDIFF': 1e-6, # Energy convergence'EDIFFG': -0.01, # Force convergence (eV/Å)'NSW': 200, # Max ionic steps'PREC': 'Accurate',
'ISMEAR': 0, # Gaussian smearing'SIGMA': 0.05,
})

SC/Static (line 143-148):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LAECHG': True, # Write core charge'LCHARG': True, # Write CHGCAR
})

ELF (line 149-156):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LELF': True, # Calculate ELF'ADDGRID': True, # Finer FFT grid'NSW': 0, # No ionic steps'IBRION': -1,
})

Electride Detection Parameters

python analyze_completed.py \
--threshold 0.6 \ # ELF threshold (0.5-0.7 typical)
--min-distance 1.5 \ # Min distance from atoms (Å)
--volume-threshold 0.5 # Min interstitial volume (ų)

Performance

Per Structure (typical, 32 cores)

Pre-screening (MatterSim):

  • Relaxation: 10-30s per structure (CPU) or 5-10s (GPU)
  • MP query: One-time per chemical system (~2-5 min, cached)
  • Hull analysis: <1s per structure

VASP calculations:

  • Relax: 2-6 hours
  • SPE job (SC + PARCHG + ELF sequential): 5-10 hours
    • SC: 1-3 hours
    • PARCHG (5 sequential): 2.5-5 hours (5 × 30-60 min)
    • ELF: 1-2 hours
  • Total VASP time: 7-16 hours/structure
  • SLURM overhead: Reduced by 75% (2 jobs instead of 8 jobs per structure)

With pre-screening (filters ~60% structures):

  • Effective time: 3-6 hours/structure (accounting for filtered structures)
  • Savings: 40-60% of total VASP computation time

Example Workflow (100 structures, max_concurrent=10, with pre-screening)

TimeActionRunningCompletedNotes
T=0Pre-screen 100 structures00MatterSim + MP
T=1hPre-screening done0060 pass, 40 filtered out
T=1hSubmit first 10 Relax jobs100Only stable structures
T=5h10 Relax done, submit 10 SPE100SPE = SC+PARCHG+ELF
T=13h10 SPE done, submit new1010~8h per SPE job
...Repeat10...
T=53hAll 60 complete06040 filtered by pre-screening

Wall time: ~53 hours for 100 structures (60 pass pre-screening)
Core-hours: ~24,000 (60 structures × 12.5h avg × 32 cores / 2 efficiency)
SLURM jobs: 120 total (vs 480 with old workflow)
Savings: 40-60% computational time from pre-screening, 75% fewer SLURM jobs


MatterSim Pre-screening

Pre-screening uses the MatterSim ML potential to quickly evaluate thermodynamic stability before running expensive VASP calculations. This is done in a separate step using prescreen.py, which generates prescreening_stability.json with structures that pass the stability threshold.

How It Works

  1. MatterSim Relaxation: Structures relaxed in batches with calculator reuse for GPU memory efficiency
  2. MP Reference Phases Query: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • The modern mp_api.client misses many stable GGA phases needed for accurate hull calculations
    • Strict filtering: only accepts entries with -GGA or -GGA+U suffix in entry_id
    • Uses uncorrected_energy (raw DFT, no MP corrections) to match MatterSim energies
    • Optional --pure-pbe flag to exclude PBE+U (use pure GGA-PBE only)
  3. Re-relax MP Structures: MP GGA structures are re-relaxed with MatterSim for consistent energy reference
  4. Convex Hull: Build phase diagram using MatterSim energies with PDEntry
  5. Output: Generate prescreening_stability.json with structures that pass threshold
  6. VASP Workflow Filter: workflow_manager.py reads prescreening_stability.json and only processes structures with E_hull < threshold (default: 0.1 eV/atom)

Key Optimizations (NEW)

Batch Processing:

  • MatterSimCalculator reused across 32 structures per batch (configurable with --batch-size)
  • Dramatically reduces GPU memory overhead and initialization time
  • Automatic GPU memory cleanup between batches
  • Supports CUDA memory expansion: PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

Complete GGA Coverage with Legacy API:

  • Uses legacy pymatgen.ext.matproj.MPRester instead of modern mp_api.client
  • Modern API misses many stable GGA phases critical for accurate hull calculations
  • Queries ALL GGA/GGA+U entries via get_entries_in_chemsys()
  • Strict suffix filtering: Only accepts entries with -GGA or -GGA+U suffix in entry_id
  • Excludes r2SCAN, SCAN, and entries without explicit functional suffix
  • Uses uncorrected_energy (raw DFT, no MP anion/composition corrections)
  • Optional --pure-pbe flag to exclude PBE+U (for pure GGA-PBE calculations only)
  • More accurate phase diagrams with comprehensive GGA reference phases

Single Global Cache Files:

  • mp_mattersim.json: All MatterSim-relaxed MP phases with chemsys field
  • mp_vaspdft.json: All MP DFT energies with chemsys field
  • Automatically handles overlapping chemical systems (e.g., B-Li-N includes B, Li, N subsystems)
  • No more separate cache directories with duplicate data

Parallel Multi-GPU Processing:

  • submit_parallel_prescreen.sh: Splits compositions across multiple GPU nodes
  • Each batch job writes to unique files:
    • JSON: prescreening_stability_batch0.json, prescreening_stability_batch1.json, ...
    • Database: prescreening_structures_batch0.db, prescreening_structures_batch1.db, ...
  • MP cache is SHARED across all batches using dual-level file locking:
    • Single file: mp_mattersim.json (all batches read/write safely)
    • Cache I/O locking: mp_mattersim.lock prevents file corruption
    • Per-chemsys locking: mp_cache_{chemsys}.lock prevents duplicate MP queries
    • When Batch 0 queries Ba-O, other batches wait for it to finish
    • After Batch 0 completes, other batches read from cache (no duplicate API calls)
    • Lock files auto-cleaned after merge
  • After all jobs complete, run merge_prescreen_batches.py to combine results
  • Command-line configurable (use --help for full options)
  • Configurable compositions per job (default: 400)
  • Linear speedup with number of GPUs
  • Example: 2000 compositions → 5 GPU nodes = 5x faster
  • Critical: File locking ensures safe concurrent access to shared MP cache

PyXtal Symmetrization:

  • Structures automatically symmetrized before MatterSim relaxation
  • Same symmetrization applied to VASP initial structures in workflow_manager.py
  • Improves convergence and consistency between pre-screening and VASP

Configuration

# Option A: Single GPU job (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--device cuda \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Pure GGA-PBE only (omit for best accuracy)# View all options
bash submit_parallel_prescreen.sh --help
# Monitor parallel jobs
squeue -u $USER| grep prescreen
# After all parallel jobs complete, merge batch results
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# This combines:# - prescreening_stability_batch*.json → prescreening_stability.json# - prescreening_structures_batch*.db → prescreening_structures.db# - mp_mattersim.json is already shared (no merging needed)# Options:# --keep-batches: preserve individual batch files (default: delete after merge)# --skip-database: skip database merge, only merge JSON (faster)# Custom options for single GPU
bash run_prescreen.sh \
--batch-size 64 \ # Larger batch (requires more GPU memory)
--hull-threshold 0.05 \ # Stricter threshold (fewer pass)
--device cuda # Use GPU (much faster than CPU)# Check results and cache
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Number of cached MP phases
cat ./VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'# By chemical system# Step 2: Run VASP workflow (automatically filters based on pre-screening)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Note: VASP structures are automatically symmetrized with PyXtal before relaxation# This ensures consistency with pre-screening and improves convergence# By default, workflow_manager.py looks for:# ./VASP_JOBS/prescreening_stability.json## To use a different file:
bash run_workflow.sh --prescreen-results /path/to/custom_results.json
# To skip filtering (process all structures):# (Not recommended - remove prescreening_stability.json first)
bash run_workflow.sh # Will warn if file not found

Performance Impact

Overhead (with optimizations):

  • Single GPU: ~30-60 minutes for 100 structures across 10 chemical systems
  • Parallel (5 GPUs): ~10-15 minutes for same dataset (5x speedup)
  • Batch processing: 3-5x faster than previous per-structure calculator creation
  • Stable phases only: 10-20x faster MP queries (20-50 phases vs 500+ phases)
  • First structure in each chemical system takes longer (MP query + cache)
  • Subsequent structures in same system benefit from shared cache

Cache Efficiency:

  • Single mp_mattersim.json file (~1-5 MB) replaces multiple per-chemsys files
  • Automatic deduplication of overlapping subsystems
  • B-Li-N system includes: B, Li, N, B-Li, B-N, Li-N, B-Li-N (7 subsystems in 1 cache)

Savings:

  • Filters 50-80% of structures (typical)
  • Saves 4-10 VASP hours per filtered structure
  • Net savings: 40-60% of total computation time
  • Additional: Pre-screening itself is 3-5x faster with batch processing

Checking Pre-screening Results

# View pre-screening summary
cat VASP_JOBS/prescreening_stability.json | jq '.summary'# View individual results
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | { id: .structure_id, chemsys: .chemsys, E_hull: .energy_above_hull, passed: .passed_prescreening}'| less
# Count passed vs filtered
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==true)'| jq -s 'length'
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==false)'| jq -s 'length'

Pre-screening Utilities

Visualizing Energy Distribution

Use plot_e_above_hull.py to visualize the energy distribution and verify your threshold:

# Plot histogram of energy_above_hull values
python3 plot_e_above_hull.py \
--input ./VASP_JOBS/prescreening_stability.json \
--output histogram.png \
--bins 100 \
--max-energy 2.0

Extracting Stable Structures

Use extract_stable_structs.py to extract CIF files for structures that passed pre-screening:

# Extract CIF files for structures that passed pre-screening
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

Troubleshooting

All structures filtered out:

  • Threshold may be too strict (try --hull-threshold 0.2)
  • Check if MP API key is working
  • Verify MatterSim is installed correctly

Pre-screening taking too long:

  • Use GPU: --device cuda
  • MP cache should build once per chemical system
  • Check MP API rate limits (built-in backoff)

SLURM Job Management Reference

Basic SLURM Commands

ActionCommand
Submit workflow managerbash run_workflow.sh --max-concurrent 20
Check job queuesqueue -u $USER
Check specific jobsqueue -j <JOBID>
View job logtail -f workflow_manager_<JOBID>.out
Cancel jobscancel <JOBID>
Job historysacct -u $USER
Job detailsscontrol show job <JOBID>

Typical Usage Pattern

# Day 1: Start workflow
ssh your_cluster
cd /scratch/$USER/vaspflow
bash run_workflow.sh --max-concurrent 20
# Note the job ID, then log out# Day 2: Check progress (from anywhere)
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if manager is still running
squeue -u $USER| grep vaspflow_manager
# Check workflow progress
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# View manager log
tail -f workflow_manager_*.out

Files

FilePurpose
prescreen.pyMatterSim pre-screening with batch processing
run_prescreen.shSubmit single-GPU pre-screening wrapper
submit_prescreen.shSLURM script for single-GPU pre-screening
submit_parallel_prescreen.shNEW: Parallel multi-GPU prescreening across nodes
merge_prescreen_batches.pyNEW: Merge parallel batch results into single file
plot_e_above_hull.pyVisualize pre-screening energy distribution
extract_stable_structs.pyExtract CIF files for stable structures
workflow_manager.pyVASP workflow with PyXtal symmetrization
run_workflow.shSubmit workflow wrapper (user-facing)
submit_workflow_manager.shSLURM script for workflow manager
workflow_status.pyStatus checking and reporting
reset_failed_jobs.pyReset failed jobs to retry (RELAX/SC/PARCHG)
compute_dft_e_hull.pyCompute DFT energy_above_hull + MatterSim comparison
run_dft_e_hull.shSubmit DFT hull wrapper (user-facing)
submit_dft_e_hull.shSLURM script for DFT hull calculation
compare_energy_methods.pyCompare MatterSim vs DFT energies (uses dft_stability_results.json)
run_compare_energy_method.shSubmit energy method comparison wrapper
submit_compare_energy_method.shSLURM script for energy method comparison
analyze.pyOrchestrates electride analysis (calls Electride.py)
analyze.shSLURM script for analysis job
Electride.pyBader analysis on ELFCAR + PARCHG files
submit_analysis.shSubmit analysis wrapper (user-facing)
filter_comb_db.pyNEW: Filter candidates with stricter volume criteria + PyXtal symmetry
extract_electride_struct.pyExtract CIF files from filtered database
generate_parchg_incars.pyHelper script to generate PARCHG INCARs from vasprun.xml-SC

Key Features:

  • Unified SPE workflow: SC-PARCHG-ELF run sequentially in one SLURM job (2 jobs per structure vs 8)
  • Simplified directory structure: Relax/ and SPE/ subdirectories (vs 7+ subdirectories)
  • Stage markers: SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE track progress within SPE job
  • Reduced SLURM overhead: 75% fewer jobs submitted to queue
  • Clean code separation: Python for VASP inputs, bash for workflow orchestration
  • Helper script for PARCHG: Standalone script generates PARCHG INCARs (band indices from vasprun.xml-SC)
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied during relaxation)
  • Batch processing: prescreen.py reuses MatterSimCalculator across structures (3-5× faster)
  • Parallel prescreening: submit_parallel_prescreen.sh splits across GPU nodes (linear speedup)
  • Complete GGA coverage: Uses legacy pymatgen.ext.matproj.MPRester for comprehensive GGA/GGA+U phases
  • Strict functional filtering: Only accepts entries with -GGA or -GGA+U suffix (excludes r2SCAN/SCAN)
  • Uncorrected energies: Uses raw DFT energies (no MP corrections) for accurate hull calculations
  • Optional pure-pbe: --pure-pbe flag to filter MP entries to pure GGA-PBE only (exclude PBE+U)
  • Single cache files: mp_mattersim.json and mp_vaspdft.json in VASP_JOBS/ directory
  • PyXtal symmetrization: Automatic structure symmetrization in both prescreening and VASP workflow
  • Two-step electride filtering: Initial analysis saves all data, stricter filtering for high-quality candidates
  • Fast symmetry analysis: PyXtal-based filtering (14× faster than AFLOW)
  • Query-able database: ase db commands for filtering candidates by stability, symmetry, or volumes
  • PDEntry for hulls: Uses PDEntry instead of ComputedEntry for accurate phase diagram analysis
  • reset_failed_jobs.py resets failed VASP jobs to retry them without data loss
  • Integrated hull validation: compute_dft_e_hull.py automatically validates pre-screening accuracy with plots and statistics
  • Energy method comparison: compare_energy_methods.py uses dft_stability_results.json as single source of truth for exact consistency
  • User-friendly wrapper scripts provide consistent interface across all stages

Best Practices

  1. Run pre-screening first with prescreen.py to save 40-60% of VASP computation
  2. Use parallel prescreening (submit_parallel_prescreen.sh) for large datasets (>500 compositions)
  3. Merge batch results with merge_prescreen_batches.py after all parallel jobs complete
  4. Optimize batch size based on GPU memory: 32 for A40/A100 (48GB), 16 for smaller GPUs
  5. Wait for pre-screening to complete before starting VASP workflow
  6. Check pre-screening results (prescreening_stability.json) to verify threshold is appropriate
  7. Inspect cache files (mp_mattersim.json, mp_vaspdft.json) to verify MP data quality
  8. Submit both jobs as SLURM jobs (required on most HPC systems)
  9. Monitor from login node using workflow_status.py instead of viewing logs constantly
  10. Set reasonable max_concurrent (10-20) to avoid queue congestion
  11. Monitor your quota on /scratch periodically (cache files are now much smaller: ~1-5 MB total)
  12. Check failed jobs early to catch systematic issues
  13. Start small (test with 2-3 structures first using --max-compositions 2 --max-structures 2)
  14. Trust PyXtal symmetrization - structures are automatically symmetrized for consistency

Common Workflows

Production Run (Full Scale)

# Step 1: Pre-screening# Option A: Single GPU (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--device cuda \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets >500 compositions)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400
# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Auto-splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor with: squeue -u $USER | grep prescreen# Wait for completion, check and visualize results
cat VASP_JOBS/prescreening_stability.json | jq '.summary'
cat VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'
jq '.results[] | select(.passed_prescreening == true) | {structure_id, energy_above_hull}' VASP_JOBS/prescreening_stability.json
python3 plot_e_above_hull.py --bins 100
# (Optional) Extract stable structures for inspection
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# Step 2: VASP workflow (structures automatically symmetrized with PyXtal)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0 \
--check-interval 120
# Step 3: Analyze electride candidates
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# Step 4: Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# Step 5: Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Step 6: Query and explore
ase db electride_candidates.db
ase db electride_candidates.db 'e_above_hull<0.05' -s space_group_number-

Resume After Interruption

# Check if still running
squeue -u $USER| grep vaspflow_manager
# If stopped, restart - database persists
bash run_workflow.sh --max-concurrent 20

Integration with MatterGen

# 1. Generate structures with MatterGencd~/mattergen_test/ternary_electride
bash generate_ternary_csp.sh
# 2. Transfer to HPC scratchcd /scratch/$USER
cp -r ~/mattergen_test/results/ternary_csp_electrides mattergen_results/
# 3. Run pre-screening (as SLURM job)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Wait for pre-screening to complete
squeue -u $USER| grep prescreen
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 3b. Visualize and extract stable structures (optional)
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 4. Start VASP workflow (as SLURM job)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20
# 5. Monitor and analyze
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# 6. Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# 7. Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# 8. Query candidates
ase db electride_candidates.db 'e_above_hull<0.05'

Credits & References

Credits:

Tools & Libraries:

Key Paper:

@article{zhuComputationalDiscoveryInorganic2019,
title = {Computational {{Discovery}} of {{Inorganic Electrides}} from an {{Automated Screening}}},
author = {Zhu, Qiang and Frolov, Timofey and Choudhary, Kamal},
year = 2019,
month = nov,
journal = {Matter},
volume = {1},
number = {5},
pages = {1293--1303},
issn = {2590-2385},
doi = {10.1016/j.matt.2019.06.017},
}
@misc{tao2026acceleratedinorganicelectridesdiscovery,
title={Accelerated Inorganic Electrides Discovery by Generative Models and Hierarchical Screening}, author={Shuo Tao and Qiang Zhu},
year={2026},
eprint={2601.21077},
archivePrefix={arXiv},
primaryClass={cond-mat.mtrl-sci},
url={https://arxiv.org/abs/2601.21077}, }

About

DFT-HT Workflow for screening inorganic electrides

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ElectrideFlow - High-Throughput Inorganic Electride Discovery Workflow Accelerated by Generative Models and Hierarchical Prescreening

A four-stage intelligent workflow for high-throughput inorganic electride discovery on HPC clusters:

  1. Chemical Exploration - Generative AI models (MatterGen) explore composition space targeting electride-favorable chemistries
  2. Stability Screening - MatterSim (MLP) pre-screening filters structures by energy above hull before expensive DFT calculations
  3. Electride Identification - Coarse DFT relaxation with ELF & PARCHG topological analysis to identify electride candidates
  4. Refinement - Tight DFT relaxation with refined convex hull analysis for final candidate validation

Table of Contents


Features

MatterSim pre-screening - filter structures by energy_above_hull before VASP (saves 40-60% computation)
Batch processing - reuses MatterSimCalculator across structures for GPU memory efficiency
Parallel prescreening - split prescreening across multiple GPU nodes for faster throughput
Stable phases only - queries only on-hull MP phases for accurate, fast convex hull analysis
Smart caching - single global cache files (mp_mattersim.json, mp_vaspdft.json) handle overlapping systems
PyXtal symmetrization - automatic structure symmetrization for better VASP convergence
Unified SPE workflow - SC-PARCHG-ELF in single job (75% fewer SLURM jobs)
Batch submission - submit n structures at a time, auto-submit more as jobs complete
Dynamic monitoring - check status and submit new jobs automatically
Local JSON database - no network dependencies, works on HPC
Smart workflow - Pre-screen → Relax → SPE (SC + PARCHG + ELF sequential)
PARCHG analysis - band-edge charge density for accurate electride identification
Two-step filtering - initial analysis saves all, stricter filtering for candidates
Fast symmetry - PyXtal-based (14× faster than AFLOW)
Query-able database - ase db commands for candidate exploration
Pymatgen input generation - INCAR, POSCAR, POTCAR, KPOINTS
Bader analysis - identify electride candidates with topological analysis
Interrupt-safe - resume from any interruption
HPC-friendly - workflow manager runs as SLURM job


Quick Start

1. Setup Environment

# On HPC login nodecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# Copy files from your local machine:# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow orchestration# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Monitor workflow progress# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# Load CUDA runtime (check your HPC's available versions, need >= 11.8)
module load cuda/11.8
# Create conda environment
conda create -n mattersim python=3.10
conda activate mattersim
# Install PyTorch with matching CUDA version FIRST# (adjust cu118 to match your loaded CUDA module)
pip install torch==2.5.1+cu118 torchvision==0.20.1+cu118 torchaudio==2.5.1+cu118 \
--index-url https://download.pytorch.org/whl/cu118
pip install torch_scatter==2.1.2+pt25cu118 torch_sparse==0.6.18+pt25cu118 \
torch_cluster==1.6.3+pt25cu118 torch_spline_conv==1.2.2+pt25cu118 \
-f https://data.pyg.org/whl/torch-2.5.1+cu118.html
pip install torch-geometric==2.7.0 pytorch-lightning==2.0.6
# Install pymatgen/mp-api (pinned versions for MP API compatibility)
pip install pymatgen==2024.10.29 mp-api==0.43.0 monty==2024.7.30 emmet-core==0.84.10
# Install other dependencies
pip install numpy>=2.0 ase==3.23.0 pyxtal==1.1.1
# Install MatterSim last (--no-deps to avoid overriding torch versions)
pip install mattersim --no-deps
# Then install any missing mattersim deps that don't conflict:
pip install torch-ema torch-runstats torchmetrics
# Set environment variables in ~/.bashrcecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc

2. Pre-screening with MatterSim (NEW Step)

# Option A: Single GPU job (for small datasets)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--device cuda \
--compositions-per-job 400
# Optional: Add --pure-pbe flag to filter MP entries to pure GGA-PBE only# (default is mixed PBE/PBE+U which is recommended for best accuracy)# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Automatically splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# When done, check results
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# View cache files (single global files with chemsys field)
ls -lh ./VASP_JOBS/mp_mattersim.json
cat ./VASP_JOBS/mp_mattersim.json | jq '.[0]'# (Optional) Visualize results and extract CIF files
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

3. VASP Workflow (Run After Pre-screening)

# Submit VASP workflow manager (processes structures that passed pre-screening)cd /scratch/$USER/vaspflow
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Check job status
squeue -u $USER
tail -f workflow_manager_<JOBID>.out

4. Monitor Progress

cd /scratch/$USER/vaspflow
conda activate mattersim
# Check workflow manager job
squeue -u $USER# View workflow manager log
tail -f workflow_manager_<JOBID>.out
# Overall workflow status
python workflow_status.py ./VASP_JOBS/workflow.json
# Composition breakdown
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# Running VASP jobs
python workflow_status.py ./VASP_JOBS/workflow.json --running
# Failed structures
python workflow_status.py ./VASP_JOBS/workflow.json --failed

5. Analyze Results

# Submit electride analysis as SLURM job
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# When complete, view all analyzed structures
cat electride_analysis.csv
# Filter with stricter criteria to get high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# View filtered candidates
cat electride_candidates.csv
# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Query database for specific criteria
ase db electride_candidates.db 'e_above_hull<0.05'

Complete Setup Guide

Initial Setup (One-time)

# 1. SSH to HPC
ssh your_cluster
# 2. Create conda environment with all dependencies
conda create -n mattersim python=3.10
conda activate mattersim
conda install -c conda-forge pymatgen mp-api
pip install mattersim ase
# 3. Setup workspacecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# 4. Upload workflow scripts from your local machine# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Status monitoring# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# 5. Make scripts executable
chmod +x *.py *.sh
# 6. Set environment variablesecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc
# 7. Verify setup
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
echo"MP API Key: $MP_API_KEY"

Starting a Workflow

# 1. SSH to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# 2. Run pre-screening first (MatterSim + MP)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# Wait for pre-screening to complete (~1-2 hours for 100 structures)# Check results:
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 2b. (Optional) Visualize and extract stable structures
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 3. Submit VASP workflow manager (processes passing structures)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20 \
--max-structures 0
# 4. Monitor (optional)
squeue -u $USER# Check job status
tail -f workflow_manager_*.out # View log# You can now safely log out - workflow runs as SLURM job!

Resuming After Interruption

# SSH back to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if workflow manager is still running
squeue -u $USER| grep vaspflow_manager
# If not running, resubmit (database persists!)
bash run_workflow.sh --max-concurrent 20
# It automatically resumes from saved state in workflow.json

Workflow Overview

Architecture

MatterGen Structures
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 1: Pre-screening (prescreen.py + MatterSim) │
│ - SLURM job on compute node │
│ - Relax structures with MatterSim ML potential │
│ - Query MP for competing phases (cached per chemical system)│
│ - Compute energy_above_hull │
│ - Output: prescreening_stability.json │
│ - Filter: only E_hull < 0.1 eV/atom proceed to VASP │
└──────────────────────────────────────────────────────────────┘
↓
prescreening_stability.json
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 2: VASP Workflow (workflow_manager.py) │
│ - SLURM job on compute node │
│ - Initialize workflow database (JSON) │
│ - Batch submission loop: │
│ * Submit up to max_concurrent VASP jobs │
│ * Each structure: Relax → SC → PARCHG* → ELF (sequential)│
│ (* PARCHG only for semiconductors, band gap > 0.01 eV) │
│ * Monitor job completion every 60s │
│ * Submit new structures as slots free up │
└──────────────────────────────────────────────────────────────┘
↓
Analyze ELF + PARCHG Results (Bader analysis)
↓
Identify Electride Candidates

Job Chain Per Structure

  1. Pre-screening (MatterSim): Quick stability check → energy_above_hull
  2. Relax (VASP): Optimize geometry → CONTCAR
  3. SC (Self-Consistent): Accurate electronic structure → CHGCAR, WAVECAR, vasprun.xml
  4. PARCHG (all materials): Band-decomposed charge density → PARCHG-band0, PARCHG-band1, PARCHG-e0025, PARCHG-e05, PARCHG-e10
  5. ELF: Calculate electron localization → ELFCAR (PARCHG files copied here for analysis)

Directory Structure

/scratch/$USER/VASP_JOBS/
├── Li10B1N3/
│ ├── Li10B1N3_s001/
│ │ ├── Relax/
│ │ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ │ ├── job.sh
│ │ │ ├── CONTCAR (after completion)
│ │ │ ├── VASP_DONE (or VASP_FAILED)
│ │ │ └── vasp_*.out/err
│ │ └── SPE/ ← Unified SC-PARCHG-ELF directory
│ │ ├── job.sh ← Single SLURM job for all stages
│ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ ├── generate_parchg_incars.py ← Helper script (copied by workflow)
│ │ ├── SC_DONE, PARCHG_DONE ← Stage markers
│ │ ├── VASP_DONE (or VASP_FAILED) ← Final completion marker
│ │ ├── INCAR-SC, OSZICAR-SC, vasprun.xml-SC ← SC outputs
│ │ ├── INCAR-PARCHG-e0025, INCAR-PARCHG-e05, INCAR-PARCHG-e10
│ │ ├── INCAR-PARCHG-band0, INCAR-PARCHG-band1
│ │ ├── PARCHG.tar.gz ← Compressed PARCHG files
│ │ ├── INCAR-ELF
│ │ ├── ELFCAR ← ELF output
│ │ ├── ELF_DONE ← ELF stage marker
│ │ └── vasp_*.out/err
│ └── Li10B1N3_s002/
├── workflow.json # Job tracking database
├── prescreening_stability.json ← Pre-screening results
├── mp_mattersim.json ← Cached MP stable phases (MatterSim energies)
├── mp_vaspdft.json ← Cached MP stable phases (DFT energies)
└── electride_candidates.json # Analysis results

Workflow States

Each structure progresses through these states in workflow_manager.py:

PENDING (structure passed pre-screening, ready for VASP)
↓
RELAX_RUNNING → RELAX_DONE → SC_RUNNING → PARCHG_RUNNING → ELF_RUNNING → ELF_DONE
↓ ↓ ↓ ↓ ↓ ↓
RELAX_FAILED (skip) SC_FAILED PARCHG_FAILED ELF_FAILED (success)
Note: SC_RUNNING, PARCHG_RUNNING, and ELF_RUNNING are all part of one SPE job
State transitions happen automatically as stage markers are detected

Note: Pre-screening (MatterSim + MP hull analysis) is done separately by prescreen.py. Only structures that pass pre-screening (E_hull < threshold) are loaded into workflow_manager.py.

Key behaviors:

  • Only structures that passed pre-screening are processed
  • Reduced SLURM jobs: 2 jobs per structure (1 Relax + 1 SPE) instead of 8 jobs
  • SPE job runs sequentially: SC -> PARCHG (5 energy windows) -> ELF in one script
  • Stage markers: SC_DONE, PARCHG_DONE, VASP_DONE track progress within SPE job
  • State transitions: Workflow manager detects markers and transitions states automatically
  • PARCHG for ALL materials: Following HT-electride methodology
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied)
  • Workflow manager automatically submits next structure when slots free up
  • Failed jobs don't block other structures
  • Max concurrent limit applies to total running structures

SPE Workflow Architecture

The unified SPE (SC-PARCHG-ELF) workflow uses a clean separation of concerns:

Python (workflow_manager.py) handles:

  • INCAR/POSCAR/POTCAR/KPOINTS for Relax, SC, ELF jobs
  • Structure loading from CIF files and symmetrization
  • Database state tracking and job orchestration
  • Directory structure creation

Helper script (generate_parchg_incars.py) handles:

  • PARCHG INCAR generation (requires parsing vasprun.xml-SC)
  • Band index calculation from NELECT and SOC parameters
  • FFT grid extraction (NGXF, NGYF, NGZF)
  • Called from bash after SC completes

Bash (job.sh in SPE/) handles:

  • Sequential execution: SC → PARCHG (5 types) → ELF
  • File copying between stages (CHGCAR-SC, WAVECAR-SC reused)
  • PARCHG output renaming (PARCHG → PARCHG-e0025, etc.)
  • PARCHG compression (PARCHG-* → PARCHG.tar.gz) to save disk space
  • Cleanup between stages to prevent VASP issues
  • Stage marker creation (SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE)

Why this design:

  • PARCHG is the ONLY calculation requiring runtime VASP output parsing
  • Keeps Python code IDE-friendly (no embedded heredocs)
  • Helper script is testable standalone
  • Other INCARs are straightforward pymatgen calls (no external scripts needed)

Monitoring

Option 1: Workflow Status Tool (Recommended)

# Overall summary
python workflow_status.py ./VASP_JOBS/workflow.json

Shows:

  • Total structures
  • Status breakdown (PENDING, RELAX_RUNNING, SC_RUNNING, etc.)
  • Currently running count
  • Completion percentage

Additional views:

# Running jobs with SLURM job IDs
python workflow_status.py workflow.json --running
# Failed structures (for debugging)
python workflow_status.py workflow.json --failed
# Composition-level summary
python workflow_status.py workflow.json --compositions
# Recently completed structures
python workflow_status.py workflow.json --completed --limit 20
# Filter by specific state
python workflow_status.py workflow.json --details --state SC_RUNNING

Option 2: Reattach to Tmux

# See live workflow output
tmux attach -t vaspflow
# View, then detach: Ctrl+B, then D

Option 3: Check SLURM Queue

# Check running jobs
squeue -u $USER# Check job history
sacct -S $(date --date="7 days ago" -I) -u $USER# Detailed job info
scontrol show job <JOBID>

Option 4: Manual Inspection

# View database directly
cat ./VASP_JOBS/workflow.json | jq '.structures | to_entries | map({id: .key, state: .value.state})'# Check specific job directorycd ./VASP_JOBS/Li10B1N3/Li10B1N3_s001/Relax
ls -lh
tail vasp_*.out
tail OSZICAR

Analyzing Results for Electride Candidates

After ELF calculations complete, analyze structures for electride characteristics using Bader topological analysis on both ELFCAR and PARCHG files.

New in v2.0: Incremental analysis with MatterSim e_above_hull integration, PyXtal database storage, and stricter candidate filtering.

Step 1: Initial Analysis (All Structures)

Recommended: Run analysis as a SLURM job (not on login node):

# Submit analysis job with defaults
bash submit_analysis.sh
# Custom settings
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# View results when complete
cat electride_analysis.csv

Output:

  • electride_analysis.csv - All analyzed structures with interstitial volumes
  • electride_data.db - PyXtal database with all structures

Step 2: Filter High-Quality Candidates

Apply stricter volume thresholds to identify high-quality electride candidates:

# Filter with default thresholds (20 ų)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# Custom thresholds (stricter)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 25 \
--min-band 25

Filtering Criteria:

  • max(e0025, e05, e10) >= min-energy (default: 20 ų)
  • max(band0, band1) >= min-band (default: 20 ų)
  • Removes duplicate structures
  • Adds PyXtal symmetry information (space groups)

Output:

  • electride_candidates.db - Filtered high-quality candidates with symmetry
  • electride_candidates.csv - CSV table for quick viewing

Step 3: Extract CIF Files

Extract CIF files for the filtered candidates:

# Extract from filtered database
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Output: electride_CIF/*.cif - One CIF file per candidate

Step 4: Query Database

Use ase db to query and filter candidates:

# View all candidates
ase db electride_candidates.db
# Sort by space group (high symmetry first)
ase db electride_candidates.db \
formula,space_group_number,e_above_hull \
-s space_group_number-
# Filter by stability (< 50 meV/atom)
ase db electride_candidates.db 'e_above_hull<0.05'# Show interstitial volumes
ase db electride_candidates.db \
formula,e0025,e05,e10,band0,band1,e_above_hull
# Cubic structures (space group >= 195)
ase db electride_candidates.db 'space_group_number>=195'# High interstitial volume (e0025 > 50 ų)
ase db electride_candidates.db 'e0025>50'

What the Analysis Does

Initial Analysis (analyze.py):

  1. Reads ELFCAR - electron localization function from VASP SPE directory
  2. Extracts PARCHG files from PARCHG.tar.gz (5 types):
    • PARCHG-band0: Valence band maximum (VBM)
    • PARCHG-band1: Second highest occupied band (VBM-1)
    • PARCHG-e0025: Energy window [-0.025, 0.025] eV around Fermi level
    • PARCHG-e05: Energy window [-0.5, 0.025] eV
    • PARCHG-e10: Energy window [-1.0, 0.025] eV
  3. Runs Bader analysis on ELFCAR and each PARCHG file
  4. Filters interstitial electrons - sites far from atoms with high localization
  5. Reports volumes of interstitial electron density (ų) for each type
  6. Adds stability data - reads e_above_hull from prescreening_stability.json
  7. Extracts spacegroup - from CONTCAR using PyXtal (adaptive tolerance)
  8. Saves to database - stores all structures in electride_data.db

Filtering (filter_comb_db.py):

  1. Applies volume thresholds - only keeps structures with substantial interstitial volumes
  2. Symmetrizes structures - uses PyXtal with adaptive tolerance (coarse→fine)
  3. Removes duplicates - identifies and filters redundant structures
  4. Adds space group info - from PyXtal symmetry analysis
  5. Creates unified database - electride_candidates.db with structures + volumes
  6. Exports CSV - electride_candidates.csv for quick viewing

Key Features (v2.0)

Incremental Analysis:

  • Automatically skips already-analyzed structures from CSV and database
  • Run repeatedly as new ELF calculations complete without re-processing
  • Perfect for monitoring ongoing workflows

Enhanced Electride Criteria:

  • Old criteria: ANY of (e0025 > 0 OR e05 > 0 OR e10 > 0 OR band0 > 0)
  • New criteria: ALL of (e0025 > 0 AND e05 > 0 AND e10 > 0 AND band0 > 0)
  • More stringent to reduce false positives

DFT Integration:

  • Reads DFT energy_above_hull from compute_dft_e_hull.py output
  • Results sorted by stability (lowest e_above_hull first)
  • Most stable electride candidates rise to the top

PyXtal Database:

  • Saves all analyzed structures to electride_data.db
  • Adaptive symmetrization (tolerances: 1e-5 to 0.5)
  • P1 fallback ensures 100% save success
  • Query-able for advanced analysis

Analysis Parameters

analyze.py:

  • --threshold: Minimum ELF value for electride detection (default: 0.6)
  • --bader-exe: Path to Bader executable (default: bader in PATH)
  • --output: Output CSV file name (default: electride_analysis.csv)
  • --pyxtal-db: PyXtal database file (default: electride_data.db)
  • --prescreening: MatterSim stability JSON (default: ./VASP_JOBS/prescreening_stability.json)
  • --workers: Number of parallel workers (default: CPU count)

filter_comb_db.py:

  • --min-energy: Minimum for max(e0025, e05, e10) in ų (default: 20)
  • --min-band: Minimum for max(band0, band1) in ų (default: 20)
  • --output: Output database (default: electride_candidates.db)
  • --output-csv: Output CSV (default: electride_candidates.csv)

Understanding Results

Initial Analysis (electride_analysis.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045
Li10B1N4_s003,Li10B1N4,0.00,0.00,0.00,5.28,0.00,12,0.068

Columns:

  • formula: Structure ID
  • composition: Chemical formula
  • e0025, e05, e10: Interstitial volumes (ų) from energy windows
  • band0, band1: Interstitial volumes (ų) from band-specific charges
  • spacegroup: PyXtal space group (1 = P1 fallback)
  • e_above_hull: MatterSim energy above hull (eV/atom)

Electride Criteria:

  • (e0025 > 0 OR e05 > 0) AND (e10 > 0 OR band0 > 0)

Filtered Candidates (electride_candidates.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045

Additional Filtering:

  • max(e0025, e05, e10) >= 20 ų (substantial energy window volume)
  • max(band0, band1) >= 20 ų (substantial band-specific volume)
  • Duplicates removed
  • Space group from PyXtal symmetry analysis

Interpreting volumes (in ų):

  • > 20: High-quality electride (passes filtering)
  • 0-20: Weak electride (filtered out by default)
  • High across multiple columns: Strong, robust electride character

Example interpretation:

  • Li10B1N4_s001: High-quality electride (all volumes > 20 ų, stable)
  • Li10B1N4_s002: Moderate electride (volumes > 12 ų, borderline)
  • Li10B1N4_s003: Not electride (very low volumes)

Sorting:

  • Both CSVs sorted by e_above_hull (low → high)
  • Most thermodynamically stable candidates appear first

Console output during analysis:

Total ELF_DONE: 100
Semiconductors (with PARCHG): 15
Metals (ELFCAR only): 85
(All structures analyzed with PARCHG in SPE workflow)
Analyzing: Li10B1N4_s001 (VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE)
Spacegroup: 166
*** ELECTRIDE CANDIDATE *** (e0025=32.62, e05=31.82, e10=31.31, band0=35.11, band1=0.00)
Analyzing: Li10B1N4_s003 (VASP_JOBS/Li10B1N4/Li10B1N4_s003/SPE)
Spacegroup: 139
Not electride (e0025=0.00, e05=0.00, e10=0.00, band0=5.28, band1=0.00)

Filter output:

======================================================================
Filtering Electride Database with Stricter Criteria
======================================================================
Criteria:
max(e0025, e05, e10) >= 20.0 ų
max(band0, band1) >= 20.0 ų
Processing structures...
Added 100 structures...
Using P1 fallback for Ba8S7_s024
Added 200 structures...
Filtering Summary:
Input structures: 6134
Filtered out (below thresholds): 4512
Duplicates removed: 89
Failed to process: 0
Added to output database: 1533

Incremental Analysis Workflow

# Day 1: 50 ELF calculations done
bash submit_analysis.sh
# Output: 50 structures analyzed# → electride_analysis.csv (50 structures)# → electride_data.db (50 structures)# Filter to get high-quality candidates
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 25 high-quality)# electride_candidates.csv# Day 2: 30 more ELF calculations done (total 80)
bash submit_analysis.sh
# Output: Only 30 new analyzed (skips existing 50)# → electride_analysis.csv updated (80 total, re-sorted)# → electride_data.db updated (80 total)# Re-filter with updated data
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 40 high-quality)# Day 3: 20 more ELF calculations done (total 100)
bash submit_analysis.sh
# Output: Only 20 new analyzed# → Final electride_analysis.csv (100 structures)# Final filtering
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: Final electride_candidates.db (e.g., 50 high-quality)# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Benefits:

  • Incremental analysis saves time (only analyzes new structures)
  • Filtering is fast (~2 min) and can be adjusted without re-running Bader
  • Database is query-able at any stage

Direct Analysis (Advanced)

The analysis uses Electride.py internally via analyze.py. For manual testing:

# Test on single structure (SPE workflow)cd VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE
python3 ../../../../Electride.py . --bader-exe ~/apps/Bader/bader
# Run full analysis with all options
python3 analyze.py \
--db VASP_JOBS/workflow.json \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv \
--pyxtal-db electride_data.db \
--prescreening VASP_JOBS/prescreening_stability.json \
--workers 32
# Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20

Requirements:

  • ELFCAR file (generated by VASP with LELF=True in SPE/)
  • PARCHG.tar.gz (5 files compressed, automatically extracted during analysis)
  • Bader executable (download from: https://theory.cm.utexas.edu/henkelman/code/bader/)
  • (Optional) prescreening_stability.json for MatterSim e_above_hull values

Output Files

Initial Analysis:

  1. electride_analysis.csv: All analyzed structures with volumes
  2. electride_data.db: PyXtal database with all structures
  3. electride_analysis_detailed.log: Full console output

Filtered Candidates:

  1. electride_candidates.csv: High-quality candidates (CSV table)
  2. electride_candidates.db: PyXtal database with filtered structures + volumes
  3. electride_CIF/: Directory with CIF files for candidates

Performance

Analysis (analyze.py):

  • Incremental mode: Only analyzes new structures (minutes for 30 new structures)
  • Full analysis: ~5-10 minutes per structure (PARCHG extraction + Bader analysis)
  • Database saves: ~1 second per structure (with adaptive tolerance)
  • Parallel processing: Scales with CPU cores (32 cores recommended)

Filtering (filter_comb_db.py):

  • Time: ~2 minutes for 6000 structures
  • PyXtal symmetry: ~0.02 sec per structure (vs AFLOW: ~0.45 sec)
  • Speedup: 14× faster than AFLOW-based workflow
  • Duplicate removal: Automatic during processing

DFT Energy Above Hull Calculation

After VASP relaxations complete, compute DFT-level thermodynamic stability using your VASP energies combined with Materials Project DFT energies for competing phases.

Energy Method Comparison

Compare energies between different calculation methods to validate pre-screening accuracy and diagnose any systematic biases:

# Run comparison (requires dft_stability_results.json)
bash run_compare_energy_method.sh \
--vasp-jobs ./VASP_JOBS \
--outlier-threshold 0.5
# Monitor job
squeue -u $USER| grep compare_energy
tail -f compare_energy_method_*.out
# Results will be in: VASP_JOBS/energy_method_comparison.json# Plots: mp_phases_comparison_*.png, generated_structures_comparison_*.png

What it compares:

  1. MP On-Hull Phases: MatterSim energies vs MP raw DFT energies
  2. Generated Structures: MatterSim energies vs VASP-DFT energies

Important: The generated structures comparison now uses dft_stability_results.json as the single source of truth for VASP energies. This ensures exact consistency with hull_comparison plots (same structures, same outlier filtering).

Key metrics:

  • Pearson correlation between methods
  • Mean Absolute Error (MAE)
  • Systematic bias detection
  • Helps diagnose non-linear hull behavior

Usage

# Submit DFT hull calculation (after VASP relaxations complete)
bash run_dft_e_hull.sh \
--vasp-jobs ./VASP_JOBS \
--output dft_stability_results.json \
--prescreen-results ./VASP_JOBS/prescreening_stability.json
# Monitor job
squeue -u $USER| grep dft_e_hull
tail -f dft_e_hull_*.out
# Hull comparison (MatterSim vs DFT) is automatically generated# if --prescreen-results is provided to compute_dft_e_hull.py# Results will be in: VASP_JOBS/hull_comparison.json# Plots: hull_comparison_scatter.png, hull_comparison_residuals.png

What It Does

  1. Scans for completed VASP relaxations (RELAX_DONE or later states)
  2. Extracts VASP energies from vasprun.xml
  3. Queries MP for stable phases only (is_stable=True) - much faster than querying all phases
  4. Uses single cache file (mp_vaspdft.json) with automatic subsystem handling
  5. Computes DFT energy_above_hull for each structure using PDEntry
  6. Outputsdft_stability_results.json with decomposition products

Output Format

{
"summary": {
"total_structures": 100,
"processed_successfully": 95,
"failed": 5,
"energy_reference": "DFT uncorrected (VASP-PBE + MP stable phases only)",
"mp_phase_selection": "stable_only (is_stable=True)",
"mp_functional_filter": "mixed_pbe_pbeU"
},
"results": [
{
"structure_id": "Li10B1N4_s001",
"composition": "Li10B1N4",
"chemsys": "B-Li-N",
"vasp_energy_per_atom": -3.45678,
"dft_energy_above_hull": 0.023,
"decomposition_products": "Li3N (0.714) + BN (0.286)",
"num_mp_stable_phases": 18,
"error": null
}
]
}

Validation: MatterSim vs DFT Hull Comparison

The compute_dft_e_hull.py script automatically validates pre-screening accuracy by comparing MatterSim vs DFT hull values when --prescreen-results is provided:

Statistical metrics:

  • Pearson correlation (how well MatterSim predicts DFT)
  • Mean Absolute Error (MAE)
  • Root Mean Square Error (RMSE)

Pre-screening performance:

  • True Positives: Correctly passed (stable in both)
  • False Positives: Incorrectly passed (unstable in DFT, wasted VASP)
  • True Negatives: Correctly filtered (unstable in both)
  • False Negatives: Incorrectly filtered (stable in DFT, missed!)
  • Precision, Recall, F1 Score
  • Computational savings (% VASP avoided)

Output: hull_comparison.json with detailed analysis

When to Use

  • After some VASP relaxations complete: Validate pre-screening accuracy early
  • Before publication: Get accurate DFT stability data
  • To identify outliers: Find structures that were incorrectly filtered/passed

Performance

  • Time: ~1-2 hours for 100 structures (mostly MP API queries)
  • Resources: 8 CPUs, 32GB RAM (for large systems)
  • Caching: Uses MP IDs from pre-screening cache to minimize API calls

Troubleshooting

Workflow Manager Not Running

Symptom: Jobs complete but database still shows RUNNING state

Check if manager job is running:

squeue -u $USER| grep vaspflow_manager

Solution: Restart workflow manager if stopped

bash run_workflow.sh --max-concurrent 10
# It will detect completed jobs and update states

Jobs Not Progressing

Check:

# Check workflow manager job
squeue -u $USER| grep vaspflow_manager
tail -f workflow_manager_*.out
# See what's completed
find ./VASP_JOBS -name "VASP_DONE"| wc -l
find ./VASP_JOBS -name "VASP_FAILED"| wc -l
# Check VASP jobs in queue
squeue -u $USER# Check database state
python workflow_status.py ./VASP_JOBS/workflow.json

Fix: Restart workflow manager if it stopped

bash run_workflow.sh --max-concurrent 10

Failed Jobs

# List all failures
python workflow_status.py workflow.json --failed
# Investigate specific failurecd ./VASP_JOBS/Li10B1N3/Li10B1N3_s003/Relax
tail -50 vasp_*.err
tail -50 OSZICAR
grep -i "error\|killed\|fail" vasp_*.out

Common failure causes:

  • Walltime limit hit (24 hours default)
  • Convergence issues (check OSZICAR)
  • Memory issues (check vasp_*.err)
  • POTCAR problems (check first few lines of vasp_*.out)

Resetting Failed Jobs for Retry

Use reset_failed_jobs.py to reset failed structures and retry them:

# Step 1: List all failed structures to understand what went wrong
python3 reset_failed_jobs.py --list
# Output shows failures grouped by stage:# RELAX_FAILED: 72 structures# SC_FAILED: 4 structures# PARCHG_FAILED: 4 structures# Step 2: Dry run to preview changes (recommended)
python3 reset_failed_jobs.py --dry-run --clean
# Step 3: Reset all failed jobs
python3 reset_failed_jobs.py --clean
# OR reset specific stage only
python3 reset_failed_jobs.py --stage RELAX --clean
python3 reset_failed_jobs.py --stage SC --clean
python3 reset_failed_jobs.py --stage PARCHG --clean
# Step 4: Resume workflow to retry
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10

What it does:

  • RELAX_FAILEDPENDING (retry from scratch)
  • SC_FAILEDRELAX_DONE (retry SC using existing relaxed structure)
  • PARCHG_FAILEDSC_DONE (retry PARCHG using existing SC results)
  • --clean flag removes VASP_FAILED markers for clean restart
  • Creates automatic backup: workflow.json.bak

Important: Investigate failure causes before blindly retrying. Some structures may have fundamental issues (bad geometry, unconverged, etc.) and will fail repeatedly.

POTCAR Not Found

# Check environmentecho$PMG_VASP_PSP_DIR# Verify structure
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
# Set if neededexport PMG_VASP_PSP_DIR=$HOME/apps/PBE64
# Add to ~/.bashrc to persist

Workflow Manager Job Issues

# Check if manager job is running
squeue -u $USER| grep vaspflow_manager
# View manager log
tail -100 workflow_manager_*.out
# Cancel stuck manager job
scancel <JOBID># Restart (database persists!)
bash run_workflow.sh --max-concurrent 10

Jobs Stuck in SLURM Queue

# Check job status
squeue -u $USER -o "%.18i %.9P %.30j %.8T %.10M %.6D %R"# Check why pending
squeue -u $USER -j <JOBID> --start
# Cancel stuck job if needed
scancel <JOBID># Workflow will mark it as failed on next check

Database Corruption

# Backup database
cp workflow.json workflow.json.backup
# Reinitialize (keeps existing directories)
python workflow_manager.py --init-only \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS
# Manually merge completed jobs from backup if needed

Parallel Pre-screening Results Missing

Symptom: After running submit_parallel_prescreen.sh, the prescreening_stability.json file is empty or only contains results from one batch.

Cause: Multiple parallel jobs writing to the same file cause race conditions and data loss.

Solution:

  1. Each batch processes a different subset of compositions using --start-composition (batch 0: comps 0-399, batch 1: 400-799, etc.)
  2. Each batch writes to its own file (prescreening_stability_batch0.json, etc.)
  3. After all jobs complete, merge them with merge_prescreen_batches.py:
# Check that all batch jobs completed
squeue -u $USER| grep prescreen # Should be empty# List batch result files
ls ./VASP_JOBS/prescreening_stability_batch*.json
ls ./VASP_JOBS/prescreening_structures_batch*.db
ls ./VASP_JOBS/mp_mattersim.json # Shared cache (not batch-specific)# Merge all batch results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# OR skip database merge (faster, JSON only)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS --skip-database
# Verify merged results
cat ./VASP_JOBS/prescreening_stability.json | jq '.metadata.total_structures'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Check shared MP cache
ls -lh ./VASP_JOBS/prescreening_structures.db # Check database exists

Prevention: Always run merge_prescreen_batches.py after parallel prescreening jobs complete.


Configuration

Key Parameters

Pre-screening (prescreen.py):

# Single GPU job
python prescreen.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0 \ # Max structures per composition
--batch-size 32 \ # Structures per batch (calculator reuse)
--mp-api-key YOUR_KEY \ # Materials Project API key
--hull-threshold 0.05 \ # E_hull threshold (eV/atom)
--device cuda \ # MatterSim device: cpu or cuda
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Automatically splits compositions across GPU nodes

VASP Workflow (workflow_manager.py):

python workflow_manager.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \ # Max structures running simultaneously
--max-compositions 20 \ # Limit number of compositions (optional)
--max-structures 0 \ # Max structures per composition
--check-interval 60 # Status check interval (seconds)

Recommendations:

  • Pre-screening:
    • --batch-size: 32 for A40/A100 GPUs (48GB VRAM), reduce to 16 for smaller GPUs
    • --hull-threshold: 0.1 eV/atom filters most unstable structures, use 0.05 for stricter filtering
    • --device: Use cuda for GPU acceleration (5-10× faster than CPU)
    • --mp-api-key: Get your free API key at https://next-gen.materialsproject.org/api
    • --pure-pbe: OPTIONAL flag to exclude PBE+U (recommended to OMIT for best accuracy)
      • Default (no flag): Mixed PBE/PBE+U (matches MP phase diagram methodology)
      • With flag: Pure GGA-PBE only (may reduce accuracy for transition metal systems)
    • MP API: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • Large datasets: Use submit_parallel_prescreen.sh to split across multiple GPUs
    • GPU memory: Set export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True in SLURM script
  • VASP Workflow:
  • --max-concurrent: 10-20 for typical HPC cluster
  • --check-interval: 60s is good balance
  • --max-compositions: Omit to process all
    • PyXtal: Structures automatically symmetrized for better convergence

SLURM Settings

Edit create_slurm_script() in workflow_manager.py (lines 163-176):

script=f"""#!/bin/bash#SBATCH --partition=Apus # Change partition#SBATCH --ntasks=32 # Change cores#SBATCH --time=1-00:00:00 # Change walltime (1 day)#SBATCH --mem=64G # Change memoery#SBATCH --output={job_dir}/vasp_%j.out#SBATCH --error={job_dir}/vasp_%j.err

VASP Input Settings

Edit create_vasp_inputs() in workflow_manager.py (lines 129-161):

Relax (line 135-142):

vis=MPRelaxSet(structure, user_incar_settings={
'EDIFF': 1e-6, # Energy convergence'EDIFFG': -0.01, # Force convergence (eV/Å)'NSW': 200, # Max ionic steps'PREC': 'Accurate',
'ISMEAR': 0, # Gaussian smearing'SIGMA': 0.05,
})

SC/Static (line 143-148):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LAECHG': True, # Write core charge'LCHARG': True, # Write CHGCAR
})

ELF (line 149-156):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LELF': True, # Calculate ELF'ADDGRID': True, # Finer FFT grid'NSW': 0, # No ionic steps'IBRION': -1,
})

Electride Detection Parameters

python analyze_completed.py \
--threshold 0.6 \ # ELF threshold (0.5-0.7 typical)
--min-distance 1.5 \ # Min distance from atoms (Å)
--volume-threshold 0.5 # Min interstitial volume (ų)

Performance

Per Structure (typical, 32 cores)

Pre-screening (MatterSim):

  • Relaxation: 10-30s per structure (CPU) or 5-10s (GPU)
  • MP query: One-time per chemical system (~2-5 min, cached)
  • Hull analysis: <1s per structure

VASP calculations:

  • Relax: 2-6 hours
  • SPE job (SC + PARCHG + ELF sequential): 5-10 hours
    • SC: 1-3 hours
    • PARCHG (5 sequential): 2.5-5 hours (5 × 30-60 min)
    • ELF: 1-2 hours
  • Total VASP time: 7-16 hours/structure
  • SLURM overhead: Reduced by 75% (2 jobs instead of 8 jobs per structure)

With pre-screening (filters ~60% structures):

  • Effective time: 3-6 hours/structure (accounting for filtered structures)
  • Savings: 40-60% of total VASP computation time

Example Workflow (100 structures, max_concurrent=10, with pre-screening)

TimeActionRunningCompletedNotes
T=0Pre-screen 100 structures00MatterSim + MP
T=1hPre-screening done0060 pass, 40 filtered out
T=1hSubmit first 10 Relax jobs100Only stable structures
T=5h10 Relax done, submit 10 SPE100SPE = SC+PARCHG+ELF
T=13h10 SPE done, submit new1010~8h per SPE job
...Repeat10...
T=53hAll 60 complete06040 filtered by pre-screening

Wall time: ~53 hours for 100 structures (60 pass pre-screening)
Core-hours: ~24,000 (60 structures × 12.5h avg × 32 cores / 2 efficiency)
SLURM jobs: 120 total (vs 480 with old workflow)
Savings: 40-60% computational time from pre-screening, 75% fewer SLURM jobs


MatterSim Pre-screening

Pre-screening uses the MatterSim ML potential to quickly evaluate thermodynamic stability before running expensive VASP calculations. This is done in a separate step using prescreen.py, which generates prescreening_stability.json with structures that pass the stability threshold.

How It Works

  1. MatterSim Relaxation: Structures relaxed in batches with calculator reuse for GPU memory efficiency
  2. MP Reference Phases Query: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • The modern mp_api.client misses many stable GGA phases needed for accurate hull calculations
    • Strict filtering: only accepts entries with -GGA or -GGA+U suffix in entry_id
    • Uses uncorrected_energy (raw DFT, no MP corrections) to match MatterSim energies
    • Optional --pure-pbe flag to exclude PBE+U (use pure GGA-PBE only)
  3. Re-relax MP Structures: MP GGA structures are re-relaxed with MatterSim for consistent energy reference
  4. Convex Hull: Build phase diagram using MatterSim energies with PDEntry
  5. Output: Generate prescreening_stability.json with structures that pass threshold
  6. VASP Workflow Filter: workflow_manager.py reads prescreening_stability.json and only processes structures with E_hull < threshold (default: 0.1 eV/atom)

Key Optimizations (NEW)

Batch Processing:

  • MatterSimCalculator reused across 32 structures per batch (configurable with --batch-size)
  • Dramatically reduces GPU memory overhead and initialization time
  • Automatic GPU memory cleanup between batches
  • Supports CUDA memory expansion: PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

Complete GGA Coverage with Legacy API:

  • Uses legacy pymatgen.ext.matproj.MPRester instead of modern mp_api.client
  • Modern API misses many stable GGA phases critical for accurate hull calculations
  • Queries ALL GGA/GGA+U entries via get_entries_in_chemsys()
  • Strict suffix filtering: Only accepts entries with -GGA or -GGA+U suffix in entry_id
  • Excludes r2SCAN, SCAN, and entries without explicit functional suffix
  • Uses uncorrected_energy (raw DFT, no MP anion/composition corrections)
  • Optional --pure-pbe flag to exclude PBE+U (for pure GGA-PBE calculations only)
  • More accurate phase diagrams with comprehensive GGA reference phases

Single Global Cache Files:

  • mp_mattersim.json: All MatterSim-relaxed MP phases with chemsys field
  • mp_vaspdft.json: All MP DFT energies with chemsys field
  • Automatically handles overlapping chemical systems (e.g., B-Li-N includes B, Li, N subsystems)
  • No more separate cache directories with duplicate data

Parallel Multi-GPU Processing:

  • submit_parallel_prescreen.sh: Splits compositions across multiple GPU nodes
  • Each batch job writes to unique files:
    • JSON: prescreening_stability_batch0.json, prescreening_stability_batch1.json, ...
    • Database: prescreening_structures_batch0.db, prescreening_structures_batch1.db, ...
  • MP cache is SHARED across all batches using dual-level file locking:
    • Single file: mp_mattersim.json (all batches read/write safely)
    • Cache I/O locking: mp_mattersim.lock prevents file corruption
    • Per-chemsys locking: mp_cache_{chemsys}.lock prevents duplicate MP queries
    • When Batch 0 queries Ba-O, other batches wait for it to finish
    • After Batch 0 completes, other batches read from cache (no duplicate API calls)
    • Lock files auto-cleaned after merge
  • After all jobs complete, run merge_prescreen_batches.py to combine results
  • Command-line configurable (use --help for full options)
  • Configurable compositions per job (default: 400)
  • Linear speedup with number of GPUs
  • Example: 2000 compositions → 5 GPU nodes = 5x faster
  • Critical: File locking ensures safe concurrent access to shared MP cache

PyXtal Symmetrization:

  • Structures automatically symmetrized before MatterSim relaxation
  • Same symmetrization applied to VASP initial structures in workflow_manager.py
  • Improves convergence and consistency between pre-screening and VASP

Configuration

# Option A: Single GPU job (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--device cuda \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Pure GGA-PBE only (omit for best accuracy)# View all options
bash submit_parallel_prescreen.sh --help
# Monitor parallel jobs
squeue -u $USER| grep prescreen
# After all parallel jobs complete, merge batch results
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# This combines:# - prescreening_stability_batch*.json → prescreening_stability.json# - prescreening_structures_batch*.db → prescreening_structures.db# - mp_mattersim.json is already shared (no merging needed)# Options:# --keep-batches: preserve individual batch files (default: delete after merge)# --skip-database: skip database merge, only merge JSON (faster)# Custom options for single GPU
bash run_prescreen.sh \
--batch-size 64 \ # Larger batch (requires more GPU memory)
--hull-threshold 0.05 \ # Stricter threshold (fewer pass)
--device cuda # Use GPU (much faster than CPU)# Check results and cache
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Number of cached MP phases
cat ./VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'# By chemical system# Step 2: Run VASP workflow (automatically filters based on pre-screening)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Note: VASP structures are automatically symmetrized with PyXtal before relaxation# This ensures consistency with pre-screening and improves convergence# By default, workflow_manager.py looks for:# ./VASP_JOBS/prescreening_stability.json## To use a different file:
bash run_workflow.sh --prescreen-results /path/to/custom_results.json
# To skip filtering (process all structures):# (Not recommended - remove prescreening_stability.json first)
bash run_workflow.sh # Will warn if file not found

Performance Impact

Overhead (with optimizations):

  • Single GPU: ~30-60 minutes for 100 structures across 10 chemical systems
  • Parallel (5 GPUs): ~10-15 minutes for same dataset (5x speedup)
  • Batch processing: 3-5x faster than previous per-structure calculator creation
  • Stable phases only: 10-20x faster MP queries (20-50 phases vs 500+ phases)
  • First structure in each chemical system takes longer (MP query + cache)
  • Subsequent structures in same system benefit from shared cache

Cache Efficiency:

  • Single mp_mattersim.json file (~1-5 MB) replaces multiple per-chemsys files
  • Automatic deduplication of overlapping subsystems
  • B-Li-N system includes: B, Li, N, B-Li, B-N, Li-N, B-Li-N (7 subsystems in 1 cache)

Savings:

  • Filters 50-80% of structures (typical)
  • Saves 4-10 VASP hours per filtered structure
  • Net savings: 40-60% of total computation time
  • Additional: Pre-screening itself is 3-5x faster with batch processing

Checking Pre-screening Results

# View pre-screening summary
cat VASP_JOBS/prescreening_stability.json | jq '.summary'# View individual results
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | { id: .structure_id, chemsys: .chemsys, E_hull: .energy_above_hull, passed: .passed_prescreening}'| less
# Count passed vs filtered
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==true)'| jq -s 'length'
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==false)'| jq -s 'length'

Pre-screening Utilities

Visualizing Energy Distribution

Use plot_e_above_hull.py to visualize the energy distribution and verify your threshold:

# Plot histogram of energy_above_hull values
python3 plot_e_above_hull.py \
--input ./VASP_JOBS/prescreening_stability.json \
--output histogram.png \
--bins 100 \
--max-energy 2.0

Extracting Stable Structures

Use extract_stable_structs.py to extract CIF files for structures that passed pre-screening:

# Extract CIF files for structures that passed pre-screening
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

Troubleshooting

All structures filtered out:

  • Threshold may be too strict (try --hull-threshold 0.2)
  • Check if MP API key is working
  • Verify MatterSim is installed correctly

Pre-screening taking too long:

  • Use GPU: --device cuda
  • MP cache should build once per chemical system
  • Check MP API rate limits (built-in backoff)

SLURM Job Management Reference

Basic SLURM Commands

ActionCommand
Submit workflow managerbash run_workflow.sh --max-concurrent 20
Check job queuesqueue -u $USER
Check specific jobsqueue -j <JOBID>
View job logtail -f workflow_manager_<JOBID>.out
Cancel jobscancel <JOBID>
Job historysacct -u $USER
Job detailsscontrol show job <JOBID>

Typical Usage Pattern

# Day 1: Start workflow
ssh your_cluster
cd /scratch/$USER/vaspflow
bash run_workflow.sh --max-concurrent 20
# Note the job ID, then log out# Day 2: Check progress (from anywhere)
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if manager is still running
squeue -u $USER| grep vaspflow_manager
# Check workflow progress
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# View manager log
tail -f workflow_manager_*.out

Files

FilePurpose
prescreen.pyMatterSim pre-screening with batch processing
run_prescreen.shSubmit single-GPU pre-screening wrapper
submit_prescreen.shSLURM script for single-GPU pre-screening
submit_parallel_prescreen.shNEW: Parallel multi-GPU prescreening across nodes
merge_prescreen_batches.pyNEW: Merge parallel batch results into single file
plot_e_above_hull.pyVisualize pre-screening energy distribution
extract_stable_structs.pyExtract CIF files for stable structures
workflow_manager.pyVASP workflow with PyXtal symmetrization
run_workflow.shSubmit workflow wrapper (user-facing)
submit_workflow_manager.shSLURM script for workflow manager
workflow_status.pyStatus checking and reporting
reset_failed_jobs.pyReset failed jobs to retry (RELAX/SC/PARCHG)
compute_dft_e_hull.pyCompute DFT energy_above_hull + MatterSim comparison
run_dft_e_hull.shSubmit DFT hull wrapper (user-facing)
submit_dft_e_hull.shSLURM script for DFT hull calculation
compare_energy_methods.pyCompare MatterSim vs DFT energies (uses dft_stability_results.json)
run_compare_energy_method.shSubmit energy method comparison wrapper
submit_compare_energy_method.shSLURM script for energy method comparison
analyze.pyOrchestrates electride analysis (calls Electride.py)
analyze.shSLURM script for analysis job
Electride.pyBader analysis on ELFCAR + PARCHG files
submit_analysis.shSubmit analysis wrapper (user-facing)
filter_comb_db.pyNEW: Filter candidates with stricter volume criteria + PyXtal symmetry
extract_electride_struct.pyExtract CIF files from filtered database
generate_parchg_incars.pyHelper script to generate PARCHG INCARs from vasprun.xml-SC

Key Features:

  • Unified SPE workflow: SC-PARCHG-ELF run sequentially in one SLURM job (2 jobs per structure vs 8)
  • Simplified directory structure: Relax/ and SPE/ subdirectories (vs 7+ subdirectories)
  • Stage markers: SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE track progress within SPE job
  • Reduced SLURM overhead: 75% fewer jobs submitted to queue
  • Clean code separation: Python for VASP inputs, bash for workflow orchestration
  • Helper script for PARCHG: Standalone script generates PARCHG INCARs (band indices from vasprun.xml-SC)
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied during relaxation)
  • Batch processing: prescreen.py reuses MatterSimCalculator across structures (3-5× faster)
  • Parallel prescreening: submit_parallel_prescreen.sh splits across GPU nodes (linear speedup)
  • Complete GGA coverage: Uses legacy pymatgen.ext.matproj.MPRester for comprehensive GGA/GGA+U phases
  • Strict functional filtering: Only accepts entries with -GGA or -GGA+U suffix (excludes r2SCAN/SCAN)
  • Uncorrected energies: Uses raw DFT energies (no MP corrections) for accurate hull calculations
  • Optional pure-pbe: --pure-pbe flag to filter MP entries to pure GGA-PBE only (exclude PBE+U)
  • Single cache files: mp_mattersim.json and mp_vaspdft.json in VASP_JOBS/ directory
  • PyXtal symmetrization: Automatic structure symmetrization in both prescreening and VASP workflow
  • Two-step electride filtering: Initial analysis saves all data, stricter filtering for high-quality candidates
  • Fast symmetry analysis: PyXtal-based filtering (14× faster than AFLOW)
  • Query-able database: ase db commands for filtering candidates by stability, symmetry, or volumes
  • PDEntry for hulls: Uses PDEntry instead of ComputedEntry for accurate phase diagram analysis
  • reset_failed_jobs.py resets failed VASP jobs to retry them without data loss
  • Integrated hull validation: compute_dft_e_hull.py automatically validates pre-screening accuracy with plots and statistics
  • Energy method comparison: compare_energy_methods.py uses dft_stability_results.json as single source of truth for exact consistency
  • User-friendly wrapper scripts provide consistent interface across all stages

Best Practices

  1. Run pre-screening first with prescreen.py to save 40-60% of VASP computation
  2. Use parallel prescreening (submit_parallel_prescreen.sh) for large datasets (>500 compositions)
  3. Merge batch results with merge_prescreen_batches.py after all parallel jobs complete
  4. Optimize batch size based on GPU memory: 32 for A40/A100 (48GB), 16 for smaller GPUs
  5. Wait for pre-screening to complete before starting VASP workflow
  6. Check pre-screening results (prescreening_stability.json) to verify threshold is appropriate
  7. Inspect cache files (mp_mattersim.json, mp_vaspdft.json) to verify MP data quality
  8. Submit both jobs as SLURM jobs (required on most HPC systems)
  9. Monitor from login node using workflow_status.py instead of viewing logs constantly
  10. Set reasonable max_concurrent (10-20) to avoid queue congestion
  11. Monitor your quota on /scratch periodically (cache files are now much smaller: ~1-5 MB total)
  12. Check failed jobs early to catch systematic issues
  13. Start small (test with 2-3 structures first using --max-compositions 2 --max-structures 2)
  14. Trust PyXtal symmetrization - structures are automatically symmetrized for consistency

Common Workflows

Production Run (Full Scale)

# Step 1: Pre-screening# Option A: Single GPU (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--device cuda \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets >500 compositions)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400
# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Auto-splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor with: squeue -u $USER | grep prescreen# Wait for completion, check and visualize results
cat VASP_JOBS/prescreening_stability.json | jq '.summary'
cat VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'
jq '.results[] | select(.passed_prescreening == true) | {structure_id, energy_above_hull}' VASP_JOBS/prescreening_stability.json
python3 plot_e_above_hull.py --bins 100
# (Optional) Extract stable structures for inspection
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# Step 2: VASP workflow (structures automatically symmetrized with PyXtal)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0 \
--check-interval 120
# Step 3: Analyze electride candidates
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# Step 4: Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# Step 5: Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Step 6: Query and explore
ase db electride_candidates.db
ase db electride_candidates.db 'e_above_hull<0.05' -s space_group_number-

Resume After Interruption

# Check if still running
squeue -u $USER| grep vaspflow_manager
# If stopped, restart - database persists
bash run_workflow.sh --max-concurrent 20

Integration with MatterGen

# 1. Generate structures with MatterGencd~/mattergen_test/ternary_electride
bash generate_ternary_csp.sh
# 2. Transfer to HPC scratchcd /scratch/$USER
cp -r ~/mattergen_test/results/ternary_csp_electrides mattergen_results/
# 3. Run pre-screening (as SLURM job)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Wait for pre-screening to complete
squeue -u $USER| grep prescreen
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 3b. Visualize and extract stable structures (optional)
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 4. Start VASP workflow (as SLURM job)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20
# 5. Monitor and analyze
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# 6. Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# 7. Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# 8. Query candidates
ase db electride_candidates.db 'e_above_hull<0.05'

Credits & References

Credits:

Tools & Libraries:

Key Paper:

@article{zhuComputationalDiscoveryInorganic2019,
title = {Computational {{Discovery}} of {{Inorganic Electrides}} from an {{Automated Screening}}},
author = {Zhu, Qiang and Frolov, Timofey and Choudhary, Kamal},
year = 2019,
month = nov,
journal = {Matter},
volume = {1},
number = {5},
pages = {1293--1303},
issn = {2590-2385},
doi = {10.1016/j.matt.2019.06.017},
}
@misc{tao2026acceleratedinorganicelectridesdiscovery,
title={Accelerated Inorganic Electrides Discovery by Generative Models and Hierarchical Screening}, author={Shuo Tao and Qiang Zhu},
year={2026},
eprint={2601.21077},
archivePrefix={arXiv},
primaryClass={cond-mat.mtrl-sci},
url={https://arxiv.org/abs/2601.21077}, }

About

DFT-HT Workflow for screening inorganic electrides

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ElectrideFlow - High-Throughput Inorganic Electride Discovery Workflow Accelerated by Generative Models and Hierarchical Prescreening

A four-stage intelligent workflow for high-throughput inorganic electride discovery on HPC clusters:

  1. Chemical Exploration - Generative AI models (MatterGen) explore composition space targeting electride-favorable chemistries
  2. Stability Screening - MatterSim (MLP) pre-screening filters structures by energy above hull before expensive DFT calculations
  3. Electride Identification - Coarse DFT relaxation with ELF & PARCHG topological analysis to identify electride candidates
  4. Refinement - Tight DFT relaxation with refined convex hull analysis for final candidate validation

Table of Contents


Features

MatterSim pre-screening - filter structures by energy_above_hull before VASP (saves 40-60% computation)
Batch processing - reuses MatterSimCalculator across structures for GPU memory efficiency
Parallel prescreening - split prescreening across multiple GPU nodes for faster throughput
Stable phases only - queries only on-hull MP phases for accurate, fast convex hull analysis
Smart caching - single global cache files (mp_mattersim.json, mp_vaspdft.json) handle overlapping systems
PyXtal symmetrization - automatic structure symmetrization for better VASP convergence
Unified SPE workflow - SC-PARCHG-ELF in single job (75% fewer SLURM jobs)
Batch submission - submit n structures at a time, auto-submit more as jobs complete
Dynamic monitoring - check status and submit new jobs automatically
Local JSON database - no network dependencies, works on HPC
Smart workflow - Pre-screen → Relax → SPE (SC + PARCHG + ELF sequential)
PARCHG analysis - band-edge charge density for accurate electride identification
Two-step filtering - initial analysis saves all, stricter filtering for candidates
Fast symmetry - PyXtal-based (14× faster than AFLOW)
Query-able database - ase db commands for candidate exploration
Pymatgen input generation - INCAR, POSCAR, POTCAR, KPOINTS
Bader analysis - identify electride candidates with topological analysis
Interrupt-safe - resume from any interruption
HPC-friendly - workflow manager runs as SLURM job


Quick Start

1. Setup Environment

# On HPC login nodecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# Copy files from your local machine:# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow orchestration# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Monitor workflow progress# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# Load CUDA runtime (check your HPC's available versions, need >= 11.8)
module load cuda/11.8
# Create conda environment
conda create -n mattersim python=3.10
conda activate mattersim
# Install PyTorch with matching CUDA version FIRST# (adjust cu118 to match your loaded CUDA module)
pip install torch==2.5.1+cu118 torchvision==0.20.1+cu118 torchaudio==2.5.1+cu118 \
--index-url https://download.pytorch.org/whl/cu118
pip install torch_scatter==2.1.2+pt25cu118 torch_sparse==0.6.18+pt25cu118 \
torch_cluster==1.6.3+pt25cu118 torch_spline_conv==1.2.2+pt25cu118 \
-f https://data.pyg.org/whl/torch-2.5.1+cu118.html
pip install torch-geometric==2.7.0 pytorch-lightning==2.0.6
# Install pymatgen/mp-api (pinned versions for MP API compatibility)
pip install pymatgen==2024.10.29 mp-api==0.43.0 monty==2024.7.30 emmet-core==0.84.10
# Install other dependencies
pip install numpy>=2.0 ase==3.23.0 pyxtal==1.1.1
# Install MatterSim last (--no-deps to avoid overriding torch versions)
pip install mattersim --no-deps
# Then install any missing mattersim deps that don't conflict:
pip install torch-ema torch-runstats torchmetrics
# Set environment variables in ~/.bashrcecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc

2. Pre-screening with MatterSim (NEW Step)

# Option A: Single GPU job (for small datasets)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--device cuda \
--compositions-per-job 400
# Optional: Add --pure-pbe flag to filter MP entries to pure GGA-PBE only# (default is mixed PBE/PBE+U which is recommended for best accuracy)# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Automatically splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# When done, check results
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# View cache files (single global files with chemsys field)
ls -lh ./VASP_JOBS/mp_mattersim.json
cat ./VASP_JOBS/mp_mattersim.json | jq '.[0]'# (Optional) Visualize results and extract CIF files
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

3. VASP Workflow (Run After Pre-screening)

# Submit VASP workflow manager (processes structures that passed pre-screening)cd /scratch/$USER/vaspflow
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Check job status
squeue -u $USER
tail -f workflow_manager_<JOBID>.out

4. Monitor Progress

cd /scratch/$USER/vaspflow
conda activate mattersim
# Check workflow manager job
squeue -u $USER# View workflow manager log
tail -f workflow_manager_<JOBID>.out
# Overall workflow status
python workflow_status.py ./VASP_JOBS/workflow.json
# Composition breakdown
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# Running VASP jobs
python workflow_status.py ./VASP_JOBS/workflow.json --running
# Failed structures
python workflow_status.py ./VASP_JOBS/workflow.json --failed

5. Analyze Results

# Submit electride analysis as SLURM job
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# When complete, view all analyzed structures
cat electride_analysis.csv
# Filter with stricter criteria to get high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# View filtered candidates
cat electride_candidates.csv
# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Query database for specific criteria
ase db electride_candidates.db 'e_above_hull<0.05'

Complete Setup Guide

Initial Setup (One-time)

# 1. SSH to HPC
ssh your_cluster
# 2. Create conda environment with all dependencies
conda create -n mattersim python=3.10
conda activate mattersim
conda install -c conda-forge pymatgen mp-api
pip install mattersim ase
# 3. Setup workspacecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# 4. Upload workflow scripts from your local machine# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Status monitoring# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# 5. Make scripts executable
chmod +x *.py *.sh
# 6. Set environment variablesecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc
# 7. Verify setup
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
echo"MP API Key: $MP_API_KEY"

Starting a Workflow

# 1. SSH to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# 2. Run pre-screening first (MatterSim + MP)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# Wait for pre-screening to complete (~1-2 hours for 100 structures)# Check results:
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 2b. (Optional) Visualize and extract stable structures
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 3. Submit VASP workflow manager (processes passing structures)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20 \
--max-structures 0
# 4. Monitor (optional)
squeue -u $USER# Check job status
tail -f workflow_manager_*.out # View log# You can now safely log out - workflow runs as SLURM job!

Resuming After Interruption

# SSH back to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if workflow manager is still running
squeue -u $USER| grep vaspflow_manager
# If not running, resubmit (database persists!)
bash run_workflow.sh --max-concurrent 20
# It automatically resumes from saved state in workflow.json

Workflow Overview

Architecture

MatterGen Structures
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 1: Pre-screening (prescreen.py + MatterSim) │
│ - SLURM job on compute node │
│ - Relax structures with MatterSim ML potential │
│ - Query MP for competing phases (cached per chemical system)│
│ - Compute energy_above_hull │
│ - Output: prescreening_stability.json │
│ - Filter: only E_hull < 0.1 eV/atom proceed to VASP │
└──────────────────────────────────────────────────────────────┘
↓
prescreening_stability.json
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 2: VASP Workflow (workflow_manager.py) │
│ - SLURM job on compute node │
│ - Initialize workflow database (JSON) │
│ - Batch submission loop: │
│ * Submit up to max_concurrent VASP jobs │
│ * Each structure: Relax → SC → PARCHG* → ELF (sequential)│
│ (* PARCHG only for semiconductors, band gap > 0.01 eV) │
│ * Monitor job completion every 60s │
│ * Submit new structures as slots free up │
└──────────────────────────────────────────────────────────────┘
↓
Analyze ELF + PARCHG Results (Bader analysis)
↓
Identify Electride Candidates

Job Chain Per Structure

  1. Pre-screening (MatterSim): Quick stability check → energy_above_hull
  2. Relax (VASP): Optimize geometry → CONTCAR
  3. SC (Self-Consistent): Accurate electronic structure → CHGCAR, WAVECAR, vasprun.xml
  4. PARCHG (all materials): Band-decomposed charge density → PARCHG-band0, PARCHG-band1, PARCHG-e0025, PARCHG-e05, PARCHG-e10
  5. ELF: Calculate electron localization → ELFCAR (PARCHG files copied here for analysis)

Directory Structure

/scratch/$USER/VASP_JOBS/
├── Li10B1N3/
│ ├── Li10B1N3_s001/
│ │ ├── Relax/
│ │ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ │ ├── job.sh
│ │ │ ├── CONTCAR (after completion)
│ │ │ ├── VASP_DONE (or VASP_FAILED)
│ │ │ └── vasp_*.out/err
│ │ └── SPE/ ← Unified SC-PARCHG-ELF directory
│ │ ├── job.sh ← Single SLURM job for all stages
│ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ ├── generate_parchg_incars.py ← Helper script (copied by workflow)
│ │ ├── SC_DONE, PARCHG_DONE ← Stage markers
│ │ ├── VASP_DONE (or VASP_FAILED) ← Final completion marker
│ │ ├── INCAR-SC, OSZICAR-SC, vasprun.xml-SC ← SC outputs
│ │ ├── INCAR-PARCHG-e0025, INCAR-PARCHG-e05, INCAR-PARCHG-e10
│ │ ├── INCAR-PARCHG-band0, INCAR-PARCHG-band1
│ │ ├── PARCHG.tar.gz ← Compressed PARCHG files
│ │ ├── INCAR-ELF
│ │ ├── ELFCAR ← ELF output
│ │ ├── ELF_DONE ← ELF stage marker
│ │ └── vasp_*.out/err
│ └── Li10B1N3_s002/
├── workflow.json # Job tracking database
├── prescreening_stability.json ← Pre-screening results
├── mp_mattersim.json ← Cached MP stable phases (MatterSim energies)
├── mp_vaspdft.json ← Cached MP stable phases (DFT energies)
└── electride_candidates.json # Analysis results

Workflow States

Each structure progresses through these states in workflow_manager.py:

PENDING (structure passed pre-screening, ready for VASP)
↓
RELAX_RUNNING → RELAX_DONE → SC_RUNNING → PARCHG_RUNNING → ELF_RUNNING → ELF_DONE
↓ ↓ ↓ ↓ ↓ ↓
RELAX_FAILED (skip) SC_FAILED PARCHG_FAILED ELF_FAILED (success)
Note: SC_RUNNING, PARCHG_RUNNING, and ELF_RUNNING are all part of one SPE job
State transitions happen automatically as stage markers are detected

Note: Pre-screening (MatterSim + MP hull analysis) is done separately by prescreen.py. Only structures that pass pre-screening (E_hull < threshold) are loaded into workflow_manager.py.

Key behaviors:

  • Only structures that passed pre-screening are processed
  • Reduced SLURM jobs: 2 jobs per structure (1 Relax + 1 SPE) instead of 8 jobs
  • SPE job runs sequentially: SC -> PARCHG (5 energy windows) -> ELF in one script
  • Stage markers: SC_DONE, PARCHG_DONE, VASP_DONE track progress within SPE job
  • State transitions: Workflow manager detects markers and transitions states automatically
  • PARCHG for ALL materials: Following HT-electride methodology
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied)
  • Workflow manager automatically submits next structure when slots free up
  • Failed jobs don't block other structures
  • Max concurrent limit applies to total running structures

SPE Workflow Architecture

The unified SPE (SC-PARCHG-ELF) workflow uses a clean separation of concerns:

Python (workflow_manager.py) handles:

  • INCAR/POSCAR/POTCAR/KPOINTS for Relax, SC, ELF jobs
  • Structure loading from CIF files and symmetrization
  • Database state tracking and job orchestration
  • Directory structure creation

Helper script (generate_parchg_incars.py) handles:

  • PARCHG INCAR generation (requires parsing vasprun.xml-SC)
  • Band index calculation from NELECT and SOC parameters
  • FFT grid extraction (NGXF, NGYF, NGZF)
  • Called from bash after SC completes

Bash (job.sh in SPE/) handles:

  • Sequential execution: SC → PARCHG (5 types) → ELF
  • File copying between stages (CHGCAR-SC, WAVECAR-SC reused)
  • PARCHG output renaming (PARCHG → PARCHG-e0025, etc.)
  • PARCHG compression (PARCHG-* → PARCHG.tar.gz) to save disk space
  • Cleanup between stages to prevent VASP issues
  • Stage marker creation (SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE)

Why this design:

  • PARCHG is the ONLY calculation requiring runtime VASP output parsing
  • Keeps Python code IDE-friendly (no embedded heredocs)
  • Helper script is testable standalone
  • Other INCARs are straightforward pymatgen calls (no external scripts needed)

Monitoring

Option 1: Workflow Status Tool (Recommended)

# Overall summary
python workflow_status.py ./VASP_JOBS/workflow.json

Shows:

  • Total structures
  • Status breakdown (PENDING, RELAX_RUNNING, SC_RUNNING, etc.)
  • Currently running count
  • Completion percentage

Additional views:

# Running jobs with SLURM job IDs
python workflow_status.py workflow.json --running
# Failed structures (for debugging)
python workflow_status.py workflow.json --failed
# Composition-level summary
python workflow_status.py workflow.json --compositions
# Recently completed structures
python workflow_status.py workflow.json --completed --limit 20
# Filter by specific state
python workflow_status.py workflow.json --details --state SC_RUNNING

Option 2: Reattach to Tmux

# See live workflow output
tmux attach -t vaspflow
# View, then detach: Ctrl+B, then D

Option 3: Check SLURM Queue

# Check running jobs
squeue -u $USER# Check job history
sacct -S $(date --date="7 days ago" -I) -u $USER# Detailed job info
scontrol show job <JOBID>

Option 4: Manual Inspection

# View database directly
cat ./VASP_JOBS/workflow.json | jq '.structures | to_entries | map({id: .key, state: .value.state})'# Check specific job directorycd ./VASP_JOBS/Li10B1N3/Li10B1N3_s001/Relax
ls -lh
tail vasp_*.out
tail OSZICAR

Analyzing Results for Electride Candidates

After ELF calculations complete, analyze structures for electride characteristics using Bader topological analysis on both ELFCAR and PARCHG files.

New in v2.0: Incremental analysis with MatterSim e_above_hull integration, PyXtal database storage, and stricter candidate filtering.

Step 1: Initial Analysis (All Structures)

Recommended: Run analysis as a SLURM job (not on login node):

# Submit analysis job with defaults
bash submit_analysis.sh
# Custom settings
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# View results when complete
cat electride_analysis.csv

Output:

  • electride_analysis.csv - All analyzed structures with interstitial volumes
  • electride_data.db - PyXtal database with all structures

Step 2: Filter High-Quality Candidates

Apply stricter volume thresholds to identify high-quality electride candidates:

# Filter with default thresholds (20 ų)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# Custom thresholds (stricter)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 25 \
--min-band 25

Filtering Criteria:

  • max(e0025, e05, e10) >= min-energy (default: 20 ų)
  • max(band0, band1) >= min-band (default: 20 ų)
  • Removes duplicate structures
  • Adds PyXtal symmetry information (space groups)

Output:

  • electride_candidates.db - Filtered high-quality candidates with symmetry
  • electride_candidates.csv - CSV table for quick viewing

Step 3: Extract CIF Files

Extract CIF files for the filtered candidates:

# Extract from filtered database
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Output: electride_CIF/*.cif - One CIF file per candidate

Step 4: Query Database

Use ase db to query and filter candidates:

# View all candidates
ase db electride_candidates.db
# Sort by space group (high symmetry first)
ase db electride_candidates.db \
formula,space_group_number,e_above_hull \
-s space_group_number-
# Filter by stability (< 50 meV/atom)
ase db electride_candidates.db 'e_above_hull<0.05'# Show interstitial volumes
ase db electride_candidates.db \
formula,e0025,e05,e10,band0,band1,e_above_hull
# Cubic structures (space group >= 195)
ase db electride_candidates.db 'space_group_number>=195'# High interstitial volume (e0025 > 50 ų)
ase db electride_candidates.db 'e0025>50'

What the Analysis Does

Initial Analysis (analyze.py):

  1. Reads ELFCAR - electron localization function from VASP SPE directory
  2. Extracts PARCHG files from PARCHG.tar.gz (5 types):
    • PARCHG-band0: Valence band maximum (VBM)
    • PARCHG-band1: Second highest occupied band (VBM-1)
    • PARCHG-e0025: Energy window [-0.025, 0.025] eV around Fermi level
    • PARCHG-e05: Energy window [-0.5, 0.025] eV
    • PARCHG-e10: Energy window [-1.0, 0.025] eV
  3. Runs Bader analysis on ELFCAR and each PARCHG file
  4. Filters interstitial electrons - sites far from atoms with high localization
  5. Reports volumes of interstitial electron density (ų) for each type
  6. Adds stability data - reads e_above_hull from prescreening_stability.json
  7. Extracts spacegroup - from CONTCAR using PyXtal (adaptive tolerance)
  8. Saves to database - stores all structures in electride_data.db

Filtering (filter_comb_db.py):

  1. Applies volume thresholds - only keeps structures with substantial interstitial volumes
  2. Symmetrizes structures - uses PyXtal with adaptive tolerance (coarse→fine)
  3. Removes duplicates - identifies and filters redundant structures
  4. Adds space group info - from PyXtal symmetry analysis
  5. Creates unified database - electride_candidates.db with structures + volumes
  6. Exports CSV - electride_candidates.csv for quick viewing

Key Features (v2.0)

Incremental Analysis:

  • Automatically skips already-analyzed structures from CSV and database
  • Run repeatedly as new ELF calculations complete without re-processing
  • Perfect for monitoring ongoing workflows

Enhanced Electride Criteria:

  • Old criteria: ANY of (e0025 > 0 OR e05 > 0 OR e10 > 0 OR band0 > 0)
  • New criteria: ALL of (e0025 > 0 AND e05 > 0 AND e10 > 0 AND band0 > 0)
  • More stringent to reduce false positives

DFT Integration:

  • Reads DFT energy_above_hull from compute_dft_e_hull.py output
  • Results sorted by stability (lowest e_above_hull first)
  • Most stable electride candidates rise to the top

PyXtal Database:

  • Saves all analyzed structures to electride_data.db
  • Adaptive symmetrization (tolerances: 1e-5 to 0.5)
  • P1 fallback ensures 100% save success
  • Query-able for advanced analysis

Analysis Parameters

analyze.py:

  • --threshold: Minimum ELF value for electride detection (default: 0.6)
  • --bader-exe: Path to Bader executable (default: bader in PATH)
  • --output: Output CSV file name (default: electride_analysis.csv)
  • --pyxtal-db: PyXtal database file (default: electride_data.db)
  • --prescreening: MatterSim stability JSON (default: ./VASP_JOBS/prescreening_stability.json)
  • --workers: Number of parallel workers (default: CPU count)

filter_comb_db.py:

  • --min-energy: Minimum for max(e0025, e05, e10) in ų (default: 20)
  • --min-band: Minimum for max(band0, band1) in ų (default: 20)
  • --output: Output database (default: electride_candidates.db)
  • --output-csv: Output CSV (default: electride_candidates.csv)

Understanding Results

Initial Analysis (electride_analysis.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045
Li10B1N4_s003,Li10B1N4,0.00,0.00,0.00,5.28,0.00,12,0.068

Columns:

  • formula: Structure ID
  • composition: Chemical formula
  • e0025, e05, e10: Interstitial volumes (ų) from energy windows
  • band0, band1: Interstitial volumes (ų) from band-specific charges
  • spacegroup: PyXtal space group (1 = P1 fallback)
  • e_above_hull: MatterSim energy above hull (eV/atom)

Electride Criteria:

  • (e0025 > 0 OR e05 > 0) AND (e10 > 0 OR band0 > 0)

Filtered Candidates (electride_candidates.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045

Additional Filtering:

  • max(e0025, e05, e10) >= 20 ų (substantial energy window volume)
  • max(band0, band1) >= 20 ų (substantial band-specific volume)
  • Duplicates removed
  • Space group from PyXtal symmetry analysis

Interpreting volumes (in ų):

  • > 20: High-quality electride (passes filtering)
  • 0-20: Weak electride (filtered out by default)
  • High across multiple columns: Strong, robust electride character

Example interpretation:

  • Li10B1N4_s001: High-quality electride (all volumes > 20 ų, stable)
  • Li10B1N4_s002: Moderate electride (volumes > 12 ų, borderline)
  • Li10B1N4_s003: Not electride (very low volumes)

Sorting:

  • Both CSVs sorted by e_above_hull (low → high)
  • Most thermodynamically stable candidates appear first

Console output during analysis:

Total ELF_DONE: 100
Semiconductors (with PARCHG): 15
Metals (ELFCAR only): 85
(All structures analyzed with PARCHG in SPE workflow)
Analyzing: Li10B1N4_s001 (VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE)
Spacegroup: 166
*** ELECTRIDE CANDIDATE *** (e0025=32.62, e05=31.82, e10=31.31, band0=35.11, band1=0.00)
Analyzing: Li10B1N4_s003 (VASP_JOBS/Li10B1N4/Li10B1N4_s003/SPE)
Spacegroup: 139
Not electride (e0025=0.00, e05=0.00, e10=0.00, band0=5.28, band1=0.00)

Filter output:

======================================================================
Filtering Electride Database with Stricter Criteria
======================================================================
Criteria:
max(e0025, e05, e10) >= 20.0 ų
max(band0, band1) >= 20.0 ų
Processing structures...
Added 100 structures...
Using P1 fallback for Ba8S7_s024
Added 200 structures...
Filtering Summary:
Input structures: 6134
Filtered out (below thresholds): 4512
Duplicates removed: 89
Failed to process: 0
Added to output database: 1533

Incremental Analysis Workflow

# Day 1: 50 ELF calculations done
bash submit_analysis.sh
# Output: 50 structures analyzed# → electride_analysis.csv (50 structures)# → electride_data.db (50 structures)# Filter to get high-quality candidates
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 25 high-quality)# electride_candidates.csv# Day 2: 30 more ELF calculations done (total 80)
bash submit_analysis.sh
# Output: Only 30 new analyzed (skips existing 50)# → electride_analysis.csv updated (80 total, re-sorted)# → electride_data.db updated (80 total)# Re-filter with updated data
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 40 high-quality)# Day 3: 20 more ELF calculations done (total 100)
bash submit_analysis.sh
# Output: Only 20 new analyzed# → Final electride_analysis.csv (100 structures)# Final filtering
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: Final electride_candidates.db (e.g., 50 high-quality)# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Benefits:

  • Incremental analysis saves time (only analyzes new structures)
  • Filtering is fast (~2 min) and can be adjusted without re-running Bader
  • Database is query-able at any stage

Direct Analysis (Advanced)

The analysis uses Electride.py internally via analyze.py. For manual testing:

# Test on single structure (SPE workflow)cd VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE
python3 ../../../../Electride.py . --bader-exe ~/apps/Bader/bader
# Run full analysis with all options
python3 analyze.py \
--db VASP_JOBS/workflow.json \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv \
--pyxtal-db electride_data.db \
--prescreening VASP_JOBS/prescreening_stability.json \
--workers 32
# Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20

Requirements:

  • ELFCAR file (generated by VASP with LELF=True in SPE/)
  • PARCHG.tar.gz (5 files compressed, automatically extracted during analysis)
  • Bader executable (download from: https://theory.cm.utexas.edu/henkelman/code/bader/)
  • (Optional) prescreening_stability.json for MatterSim e_above_hull values

Output Files

Initial Analysis:

  1. electride_analysis.csv: All analyzed structures with volumes
  2. electride_data.db: PyXtal database with all structures
  3. electride_analysis_detailed.log: Full console output

Filtered Candidates:

  1. electride_candidates.csv: High-quality candidates (CSV table)
  2. electride_candidates.db: PyXtal database with filtered structures + volumes
  3. electride_CIF/: Directory with CIF files for candidates

Performance

Analysis (analyze.py):

  • Incremental mode: Only analyzes new structures (minutes for 30 new structures)
  • Full analysis: ~5-10 minutes per structure (PARCHG extraction + Bader analysis)
  • Database saves: ~1 second per structure (with adaptive tolerance)
  • Parallel processing: Scales with CPU cores (32 cores recommended)

Filtering (filter_comb_db.py):

  • Time: ~2 minutes for 6000 structures
  • PyXtal symmetry: ~0.02 sec per structure (vs AFLOW: ~0.45 sec)
  • Speedup: 14× faster than AFLOW-based workflow
  • Duplicate removal: Automatic during processing

DFT Energy Above Hull Calculation

After VASP relaxations complete, compute DFT-level thermodynamic stability using your VASP energies combined with Materials Project DFT energies for competing phases.

Energy Method Comparison

Compare energies between different calculation methods to validate pre-screening accuracy and diagnose any systematic biases:

# Run comparison (requires dft_stability_results.json)
bash run_compare_energy_method.sh \
--vasp-jobs ./VASP_JOBS \
--outlier-threshold 0.5
# Monitor job
squeue -u $USER| grep compare_energy
tail -f compare_energy_method_*.out
# Results will be in: VASP_JOBS/energy_method_comparison.json# Plots: mp_phases_comparison_*.png, generated_structures_comparison_*.png

What it compares:

  1. MP On-Hull Phases: MatterSim energies vs MP raw DFT energies
  2. Generated Structures: MatterSim energies vs VASP-DFT energies

Important: The generated structures comparison now uses dft_stability_results.json as the single source of truth for VASP energies. This ensures exact consistency with hull_comparison plots (same structures, same outlier filtering).

Key metrics:

  • Pearson correlation between methods
  • Mean Absolute Error (MAE)
  • Systematic bias detection
  • Helps diagnose non-linear hull behavior

Usage

# Submit DFT hull calculation (after VASP relaxations complete)
bash run_dft_e_hull.sh \
--vasp-jobs ./VASP_JOBS \
--output dft_stability_results.json \
--prescreen-results ./VASP_JOBS/prescreening_stability.json
# Monitor job
squeue -u $USER| grep dft_e_hull
tail -f dft_e_hull_*.out
# Hull comparison (MatterSim vs DFT) is automatically generated# if --prescreen-results is provided to compute_dft_e_hull.py# Results will be in: VASP_JOBS/hull_comparison.json# Plots: hull_comparison_scatter.png, hull_comparison_residuals.png

What It Does

  1. Scans for completed VASP relaxations (RELAX_DONE or later states)
  2. Extracts VASP energies from vasprun.xml
  3. Queries MP for stable phases only (is_stable=True) - much faster than querying all phases
  4. Uses single cache file (mp_vaspdft.json) with automatic subsystem handling
  5. Computes DFT energy_above_hull for each structure using PDEntry
  6. Outputsdft_stability_results.json with decomposition products

Output Format

{
"summary": {
"total_structures": 100,
"processed_successfully": 95,
"failed": 5,
"energy_reference": "DFT uncorrected (VASP-PBE + MP stable phases only)",
"mp_phase_selection": "stable_only (is_stable=True)",
"mp_functional_filter": "mixed_pbe_pbeU"
},
"results": [
{
"structure_id": "Li10B1N4_s001",
"composition": "Li10B1N4",
"chemsys": "B-Li-N",
"vasp_energy_per_atom": -3.45678,
"dft_energy_above_hull": 0.023,
"decomposition_products": "Li3N (0.714) + BN (0.286)",
"num_mp_stable_phases": 18,
"error": null
}
]
}

Validation: MatterSim vs DFT Hull Comparison

The compute_dft_e_hull.py script automatically validates pre-screening accuracy by comparing MatterSim vs DFT hull values when --prescreen-results is provided:

Statistical metrics:

  • Pearson correlation (how well MatterSim predicts DFT)
  • Mean Absolute Error (MAE)
  • Root Mean Square Error (RMSE)

Pre-screening performance:

  • True Positives: Correctly passed (stable in both)
  • False Positives: Incorrectly passed (unstable in DFT, wasted VASP)
  • True Negatives: Correctly filtered (unstable in both)
  • False Negatives: Incorrectly filtered (stable in DFT, missed!)
  • Precision, Recall, F1 Score
  • Computational savings (% VASP avoided)

Output: hull_comparison.json with detailed analysis

When to Use

  • After some VASP relaxations complete: Validate pre-screening accuracy early
  • Before publication: Get accurate DFT stability data
  • To identify outliers: Find structures that were incorrectly filtered/passed

Performance

  • Time: ~1-2 hours for 100 structures (mostly MP API queries)
  • Resources: 8 CPUs, 32GB RAM (for large systems)
  • Caching: Uses MP IDs from pre-screening cache to minimize API calls

Troubleshooting

Workflow Manager Not Running

Symptom: Jobs complete but database still shows RUNNING state

Check if manager job is running:

squeue -u $USER| grep vaspflow_manager

Solution: Restart workflow manager if stopped

bash run_workflow.sh --max-concurrent 10
# It will detect completed jobs and update states

Jobs Not Progressing

Check:

# Check workflow manager job
squeue -u $USER| grep vaspflow_manager
tail -f workflow_manager_*.out
# See what's completed
find ./VASP_JOBS -name "VASP_DONE"| wc -l
find ./VASP_JOBS -name "VASP_FAILED"| wc -l
# Check VASP jobs in queue
squeue -u $USER# Check database state
python workflow_status.py ./VASP_JOBS/workflow.json

Fix: Restart workflow manager if it stopped

bash run_workflow.sh --max-concurrent 10

Failed Jobs

# List all failures
python workflow_status.py workflow.json --failed
# Investigate specific failurecd ./VASP_JOBS/Li10B1N3/Li10B1N3_s003/Relax
tail -50 vasp_*.err
tail -50 OSZICAR
grep -i "error\|killed\|fail" vasp_*.out

Common failure causes:

  • Walltime limit hit (24 hours default)
  • Convergence issues (check OSZICAR)
  • Memory issues (check vasp_*.err)
  • POTCAR problems (check first few lines of vasp_*.out)

Resetting Failed Jobs for Retry

Use reset_failed_jobs.py to reset failed structures and retry them:

# Step 1: List all failed structures to understand what went wrong
python3 reset_failed_jobs.py --list
# Output shows failures grouped by stage:# RELAX_FAILED: 72 structures# SC_FAILED: 4 structures# PARCHG_FAILED: 4 structures# Step 2: Dry run to preview changes (recommended)
python3 reset_failed_jobs.py --dry-run --clean
# Step 3: Reset all failed jobs
python3 reset_failed_jobs.py --clean
# OR reset specific stage only
python3 reset_failed_jobs.py --stage RELAX --clean
python3 reset_failed_jobs.py --stage SC --clean
python3 reset_failed_jobs.py --stage PARCHG --clean
# Step 4: Resume workflow to retry
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10

What it does:

  • RELAX_FAILEDPENDING (retry from scratch)
  • SC_FAILEDRELAX_DONE (retry SC using existing relaxed structure)
  • PARCHG_FAILEDSC_DONE (retry PARCHG using existing SC results)
  • --clean flag removes VASP_FAILED markers for clean restart
  • Creates automatic backup: workflow.json.bak

Important: Investigate failure causes before blindly retrying. Some structures may have fundamental issues (bad geometry, unconverged, etc.) and will fail repeatedly.

POTCAR Not Found

# Check environmentecho$PMG_VASP_PSP_DIR# Verify structure
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
# Set if neededexport PMG_VASP_PSP_DIR=$HOME/apps/PBE64
# Add to ~/.bashrc to persist

Workflow Manager Job Issues

# Check if manager job is running
squeue -u $USER| grep vaspflow_manager
# View manager log
tail -100 workflow_manager_*.out
# Cancel stuck manager job
scancel <JOBID># Restart (database persists!)
bash run_workflow.sh --max-concurrent 10

Jobs Stuck in SLURM Queue

# Check job status
squeue -u $USER -o "%.18i %.9P %.30j %.8T %.10M %.6D %R"# Check why pending
squeue -u $USER -j <JOBID> --start
# Cancel stuck job if needed
scancel <JOBID># Workflow will mark it as failed on next check

Database Corruption

# Backup database
cp workflow.json workflow.json.backup
# Reinitialize (keeps existing directories)
python workflow_manager.py --init-only \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS
# Manually merge completed jobs from backup if needed

Parallel Pre-screening Results Missing

Symptom: After running submit_parallel_prescreen.sh, the prescreening_stability.json file is empty or only contains results from one batch.

Cause: Multiple parallel jobs writing to the same file cause race conditions and data loss.

Solution:

  1. Each batch processes a different subset of compositions using --start-composition (batch 0: comps 0-399, batch 1: 400-799, etc.)
  2. Each batch writes to its own file (prescreening_stability_batch0.json, etc.)
  3. After all jobs complete, merge them with merge_prescreen_batches.py:
# Check that all batch jobs completed
squeue -u $USER| grep prescreen # Should be empty# List batch result files
ls ./VASP_JOBS/prescreening_stability_batch*.json
ls ./VASP_JOBS/prescreening_structures_batch*.db
ls ./VASP_JOBS/mp_mattersim.json # Shared cache (not batch-specific)# Merge all batch results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# OR skip database merge (faster, JSON only)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS --skip-database
# Verify merged results
cat ./VASP_JOBS/prescreening_stability.json | jq '.metadata.total_structures'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Check shared MP cache
ls -lh ./VASP_JOBS/prescreening_structures.db # Check database exists

Prevention: Always run merge_prescreen_batches.py after parallel prescreening jobs complete.


Configuration

Key Parameters

Pre-screening (prescreen.py):

# Single GPU job
python prescreen.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0 \ # Max structures per composition
--batch-size 32 \ # Structures per batch (calculator reuse)
--mp-api-key YOUR_KEY \ # Materials Project API key
--hull-threshold 0.05 \ # E_hull threshold (eV/atom)
--device cuda \ # MatterSim device: cpu or cuda
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Automatically splits compositions across GPU nodes

VASP Workflow (workflow_manager.py):

python workflow_manager.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \ # Max structures running simultaneously
--max-compositions 20 \ # Limit number of compositions (optional)
--max-structures 0 \ # Max structures per composition
--check-interval 60 # Status check interval (seconds)

Recommendations:

  • Pre-screening:
    • --batch-size: 32 for A40/A100 GPUs (48GB VRAM), reduce to 16 for smaller GPUs
    • --hull-threshold: 0.1 eV/atom filters most unstable structures, use 0.05 for stricter filtering
    • --device: Use cuda for GPU acceleration (5-10× faster than CPU)
    • --mp-api-key: Get your free API key at https://next-gen.materialsproject.org/api
    • --pure-pbe: OPTIONAL flag to exclude PBE+U (recommended to OMIT for best accuracy)
      • Default (no flag): Mixed PBE/PBE+U (matches MP phase diagram methodology)
      • With flag: Pure GGA-PBE only (may reduce accuracy for transition metal systems)
    • MP API: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • Large datasets: Use submit_parallel_prescreen.sh to split across multiple GPUs
    • GPU memory: Set export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True in SLURM script
  • VASP Workflow:
  • --max-concurrent: 10-20 for typical HPC cluster
  • --check-interval: 60s is good balance
  • --max-compositions: Omit to process all
    • PyXtal: Structures automatically symmetrized for better convergence

SLURM Settings

Edit create_slurm_script() in workflow_manager.py (lines 163-176):

script=f"""#!/bin/bash#SBATCH --partition=Apus # Change partition#SBATCH --ntasks=32 # Change cores#SBATCH --time=1-00:00:00 # Change walltime (1 day)#SBATCH --mem=64G # Change memoery#SBATCH --output={job_dir}/vasp_%j.out#SBATCH --error={job_dir}/vasp_%j.err

VASP Input Settings

Edit create_vasp_inputs() in workflow_manager.py (lines 129-161):

Relax (line 135-142):

vis=MPRelaxSet(structure, user_incar_settings={
'EDIFF': 1e-6, # Energy convergence'EDIFFG': -0.01, # Force convergence (eV/Å)'NSW': 200, # Max ionic steps'PREC': 'Accurate',
'ISMEAR': 0, # Gaussian smearing'SIGMA': 0.05,
})

SC/Static (line 143-148):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LAECHG': True, # Write core charge'LCHARG': True, # Write CHGCAR
})

ELF (line 149-156):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LELF': True, # Calculate ELF'ADDGRID': True, # Finer FFT grid'NSW': 0, # No ionic steps'IBRION': -1,
})

Electride Detection Parameters

python analyze_completed.py \
--threshold 0.6 \ # ELF threshold (0.5-0.7 typical)
--min-distance 1.5 \ # Min distance from atoms (Å)
--volume-threshold 0.5 # Min interstitial volume (ų)

Performance

Per Structure (typical, 32 cores)

Pre-screening (MatterSim):

  • Relaxation: 10-30s per structure (CPU) or 5-10s (GPU)
  • MP query: One-time per chemical system (~2-5 min, cached)
  • Hull analysis: <1s per structure

VASP calculations:

  • Relax: 2-6 hours
  • SPE job (SC + PARCHG + ELF sequential): 5-10 hours
    • SC: 1-3 hours
    • PARCHG (5 sequential): 2.5-5 hours (5 × 30-60 min)
    • ELF: 1-2 hours
  • Total VASP time: 7-16 hours/structure
  • SLURM overhead: Reduced by 75% (2 jobs instead of 8 jobs per structure)

With pre-screening (filters ~60% structures):

  • Effective time: 3-6 hours/structure (accounting for filtered structures)
  • Savings: 40-60% of total VASP computation time

Example Workflow (100 structures, max_concurrent=10, with pre-screening)

TimeActionRunningCompletedNotes
T=0Pre-screen 100 structures00MatterSim + MP
T=1hPre-screening done0060 pass, 40 filtered out
T=1hSubmit first 10 Relax jobs100Only stable structures
T=5h10 Relax done, submit 10 SPE100SPE = SC+PARCHG+ELF
T=13h10 SPE done, submit new1010~8h per SPE job
...Repeat10...
T=53hAll 60 complete06040 filtered by pre-screening

Wall time: ~53 hours for 100 structures (60 pass pre-screening)
Core-hours: ~24,000 (60 structures × 12.5h avg × 32 cores / 2 efficiency)
SLURM jobs: 120 total (vs 480 with old workflow)
Savings: 40-60% computational time from pre-screening, 75% fewer SLURM jobs


MatterSim Pre-screening

Pre-screening uses the MatterSim ML potential to quickly evaluate thermodynamic stability before running expensive VASP calculations. This is done in a separate step using prescreen.py, which generates prescreening_stability.json with structures that pass the stability threshold.

How It Works

  1. MatterSim Relaxation: Structures relaxed in batches with calculator reuse for GPU memory efficiency
  2. MP Reference Phases Query: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • The modern mp_api.client misses many stable GGA phases needed for accurate hull calculations
    • Strict filtering: only accepts entries with -GGA or -GGA+U suffix in entry_id
    • Uses uncorrected_energy (raw DFT, no MP corrections) to match MatterSim energies
    • Optional --pure-pbe flag to exclude PBE+U (use pure GGA-PBE only)
  3. Re-relax MP Structures: MP GGA structures are re-relaxed with MatterSim for consistent energy reference
  4. Convex Hull: Build phase diagram using MatterSim energies with PDEntry
  5. Output: Generate prescreening_stability.json with structures that pass threshold
  6. VASP Workflow Filter: workflow_manager.py reads prescreening_stability.json and only processes structures with E_hull < threshold (default: 0.1 eV/atom)

Key Optimizations (NEW)

Batch Processing:

  • MatterSimCalculator reused across 32 structures per batch (configurable with --batch-size)
  • Dramatically reduces GPU memory overhead and initialization time
  • Automatic GPU memory cleanup between batches
  • Supports CUDA memory expansion: PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

Complete GGA Coverage with Legacy API:

  • Uses legacy pymatgen.ext.matproj.MPRester instead of modern mp_api.client
  • Modern API misses many stable GGA phases critical for accurate hull calculations
  • Queries ALL GGA/GGA+U entries via get_entries_in_chemsys()
  • Strict suffix filtering: Only accepts entries with -GGA or -GGA+U suffix in entry_id
  • Excludes r2SCAN, SCAN, and entries without explicit functional suffix
  • Uses uncorrected_energy (raw DFT, no MP anion/composition corrections)
  • Optional --pure-pbe flag to exclude PBE+U (for pure GGA-PBE calculations only)
  • More accurate phase diagrams with comprehensive GGA reference phases

Single Global Cache Files:

  • mp_mattersim.json: All MatterSim-relaxed MP phases with chemsys field
  • mp_vaspdft.json: All MP DFT energies with chemsys field
  • Automatically handles overlapping chemical systems (e.g., B-Li-N includes B, Li, N subsystems)
  • No more separate cache directories with duplicate data

Parallel Multi-GPU Processing:

  • submit_parallel_prescreen.sh: Splits compositions across multiple GPU nodes
  • Each batch job writes to unique files:
    • JSON: prescreening_stability_batch0.json, prescreening_stability_batch1.json, ...
    • Database: prescreening_structures_batch0.db, prescreening_structures_batch1.db, ...
  • MP cache is SHARED across all batches using dual-level file locking:
    • Single file: mp_mattersim.json (all batches read/write safely)
    • Cache I/O locking: mp_mattersim.lock prevents file corruption
    • Per-chemsys locking: mp_cache_{chemsys}.lock prevents duplicate MP queries
    • When Batch 0 queries Ba-O, other batches wait for it to finish
    • After Batch 0 completes, other batches read from cache (no duplicate API calls)
    • Lock files auto-cleaned after merge
  • After all jobs complete, run merge_prescreen_batches.py to combine results
  • Command-line configurable (use --help for full options)
  • Configurable compositions per job (default: 400)
  • Linear speedup with number of GPUs
  • Example: 2000 compositions → 5 GPU nodes = 5x faster
  • Critical: File locking ensures safe concurrent access to shared MP cache

PyXtal Symmetrization:

  • Structures automatically symmetrized before MatterSim relaxation
  • Same symmetrization applied to VASP initial structures in workflow_manager.py
  • Improves convergence and consistency between pre-screening and VASP

Configuration

# Option A: Single GPU job (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--device cuda \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Pure GGA-PBE only (omit for best accuracy)# View all options
bash submit_parallel_prescreen.sh --help
# Monitor parallel jobs
squeue -u $USER| grep prescreen
# After all parallel jobs complete, merge batch results
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# This combines:# - prescreening_stability_batch*.json → prescreening_stability.json# - prescreening_structures_batch*.db → prescreening_structures.db# - mp_mattersim.json is already shared (no merging needed)# Options:# --keep-batches: preserve individual batch files (default: delete after merge)# --skip-database: skip database merge, only merge JSON (faster)# Custom options for single GPU
bash run_prescreen.sh \
--batch-size 64 \ # Larger batch (requires more GPU memory)
--hull-threshold 0.05 \ # Stricter threshold (fewer pass)
--device cuda # Use GPU (much faster than CPU)# Check results and cache
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Number of cached MP phases
cat ./VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'# By chemical system# Step 2: Run VASP workflow (automatically filters based on pre-screening)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Note: VASP structures are automatically symmetrized with PyXtal before relaxation# This ensures consistency with pre-screening and improves convergence# By default, workflow_manager.py looks for:# ./VASP_JOBS/prescreening_stability.json## To use a different file:
bash run_workflow.sh --prescreen-results /path/to/custom_results.json
# To skip filtering (process all structures):# (Not recommended - remove prescreening_stability.json first)
bash run_workflow.sh # Will warn if file not found

Performance Impact

Overhead (with optimizations):

  • Single GPU: ~30-60 minutes for 100 structures across 10 chemical systems
  • Parallel (5 GPUs): ~10-15 minutes for same dataset (5x speedup)
  • Batch processing: 3-5x faster than previous per-structure calculator creation
  • Stable phases only: 10-20x faster MP queries (20-50 phases vs 500+ phases)
  • First structure in each chemical system takes longer (MP query + cache)
  • Subsequent structures in same system benefit from shared cache

Cache Efficiency:

  • Single mp_mattersim.json file (~1-5 MB) replaces multiple per-chemsys files
  • Automatic deduplication of overlapping subsystems
  • B-Li-N system includes: B, Li, N, B-Li, B-N, Li-N, B-Li-N (7 subsystems in 1 cache)

Savings:

  • Filters 50-80% of structures (typical)
  • Saves 4-10 VASP hours per filtered structure
  • Net savings: 40-60% of total computation time
  • Additional: Pre-screening itself is 3-5x faster with batch processing

Checking Pre-screening Results

# View pre-screening summary
cat VASP_JOBS/prescreening_stability.json | jq '.summary'# View individual results
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | { id: .structure_id, chemsys: .chemsys, E_hull: .energy_above_hull, passed: .passed_prescreening}'| less
# Count passed vs filtered
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==true)'| jq -s 'length'
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==false)'| jq -s 'length'

Pre-screening Utilities

Visualizing Energy Distribution

Use plot_e_above_hull.py to visualize the energy distribution and verify your threshold:

# Plot histogram of energy_above_hull values
python3 plot_e_above_hull.py \
--input ./VASP_JOBS/prescreening_stability.json \
--output histogram.png \
--bins 100 \
--max-energy 2.0

Extracting Stable Structures

Use extract_stable_structs.py to extract CIF files for structures that passed pre-screening:

# Extract CIF files for structures that passed pre-screening
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

Troubleshooting

All structures filtered out:

  • Threshold may be too strict (try --hull-threshold 0.2)
  • Check if MP API key is working
  • Verify MatterSim is installed correctly

Pre-screening taking too long:

  • Use GPU: --device cuda
  • MP cache should build once per chemical system
  • Check MP API rate limits (built-in backoff)

SLURM Job Management Reference

Basic SLURM Commands

ActionCommand
Submit workflow managerbash run_workflow.sh --max-concurrent 20
Check job queuesqueue -u $USER
Check specific jobsqueue -j <JOBID>
View job logtail -f workflow_manager_<JOBID>.out
Cancel jobscancel <JOBID>
Job historysacct -u $USER
Job detailsscontrol show job <JOBID>

Typical Usage Pattern

# Day 1: Start workflow
ssh your_cluster
cd /scratch/$USER/vaspflow
bash run_workflow.sh --max-concurrent 20
# Note the job ID, then log out# Day 2: Check progress (from anywhere)
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if manager is still running
squeue -u $USER| grep vaspflow_manager
# Check workflow progress
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# View manager log
tail -f workflow_manager_*.out

Files

FilePurpose
prescreen.pyMatterSim pre-screening with batch processing
run_prescreen.shSubmit single-GPU pre-screening wrapper
submit_prescreen.shSLURM script for single-GPU pre-screening
submit_parallel_prescreen.shNEW: Parallel multi-GPU prescreening across nodes
merge_prescreen_batches.pyNEW: Merge parallel batch results into single file
plot_e_above_hull.pyVisualize pre-screening energy distribution
extract_stable_structs.pyExtract CIF files for stable structures
workflow_manager.pyVASP workflow with PyXtal symmetrization
run_workflow.shSubmit workflow wrapper (user-facing)
submit_workflow_manager.shSLURM script for workflow manager
workflow_status.pyStatus checking and reporting
reset_failed_jobs.pyReset failed jobs to retry (RELAX/SC/PARCHG)
compute_dft_e_hull.pyCompute DFT energy_above_hull + MatterSim comparison
run_dft_e_hull.shSubmit DFT hull wrapper (user-facing)
submit_dft_e_hull.shSLURM script for DFT hull calculation
compare_energy_methods.pyCompare MatterSim vs DFT energies (uses dft_stability_results.json)
run_compare_energy_method.shSubmit energy method comparison wrapper
submit_compare_energy_method.shSLURM script for energy method comparison
analyze.pyOrchestrates electride analysis (calls Electride.py)
analyze.shSLURM script for analysis job
Electride.pyBader analysis on ELFCAR + PARCHG files
submit_analysis.shSubmit analysis wrapper (user-facing)
filter_comb_db.pyNEW: Filter candidates with stricter volume criteria + PyXtal symmetry
extract_electride_struct.pyExtract CIF files from filtered database
generate_parchg_incars.pyHelper script to generate PARCHG INCARs from vasprun.xml-SC

Key Features:

  • Unified SPE workflow: SC-PARCHG-ELF run sequentially in one SLURM job (2 jobs per structure vs 8)
  • Simplified directory structure: Relax/ and SPE/ subdirectories (vs 7+ subdirectories)
  • Stage markers: SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE track progress within SPE job
  • Reduced SLURM overhead: 75% fewer jobs submitted to queue
  • Clean code separation: Python for VASP inputs, bash for workflow orchestration
  • Helper script for PARCHG: Standalone script generates PARCHG INCARs (band indices from vasprun.xml-SC)
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied during relaxation)
  • Batch processing: prescreen.py reuses MatterSimCalculator across structures (3-5× faster)
  • Parallel prescreening: submit_parallel_prescreen.sh splits across GPU nodes (linear speedup)
  • Complete GGA coverage: Uses legacy pymatgen.ext.matproj.MPRester for comprehensive GGA/GGA+U phases
  • Strict functional filtering: Only accepts entries with -GGA or -GGA+U suffix (excludes r2SCAN/SCAN)
  • Uncorrected energies: Uses raw DFT energies (no MP corrections) for accurate hull calculations
  • Optional pure-pbe: --pure-pbe flag to filter MP entries to pure GGA-PBE only (exclude PBE+U)
  • Single cache files: mp_mattersim.json and mp_vaspdft.json in VASP_JOBS/ directory
  • PyXtal symmetrization: Automatic structure symmetrization in both prescreening and VASP workflow
  • Two-step electride filtering: Initial analysis saves all data, stricter filtering for high-quality candidates
  • Fast symmetry analysis: PyXtal-based filtering (14× faster than AFLOW)
  • Query-able database: ase db commands for filtering candidates by stability, symmetry, or volumes
  • PDEntry for hulls: Uses PDEntry instead of ComputedEntry for accurate phase diagram analysis
  • reset_failed_jobs.py resets failed VASP jobs to retry them without data loss
  • Integrated hull validation: compute_dft_e_hull.py automatically validates pre-screening accuracy with plots and statistics
  • Energy method comparison: compare_energy_methods.py uses dft_stability_results.json as single source of truth for exact consistency
  • User-friendly wrapper scripts provide consistent interface across all stages

Best Practices

  1. Run pre-screening first with prescreen.py to save 40-60% of VASP computation
  2. Use parallel prescreening (submit_parallel_prescreen.sh) for large datasets (>500 compositions)
  3. Merge batch results with merge_prescreen_batches.py after all parallel jobs complete
  4. Optimize batch size based on GPU memory: 32 for A40/A100 (48GB), 16 for smaller GPUs
  5. Wait for pre-screening to complete before starting VASP workflow
  6. Check pre-screening results (prescreening_stability.json) to verify threshold is appropriate
  7. Inspect cache files (mp_mattersim.json, mp_vaspdft.json) to verify MP data quality
  8. Submit both jobs as SLURM jobs (required on most HPC systems)
  9. Monitor from login node using workflow_status.py instead of viewing logs constantly
  10. Set reasonable max_concurrent (10-20) to avoid queue congestion
  11. Monitor your quota on /scratch periodically (cache files are now much smaller: ~1-5 MB total)
  12. Check failed jobs early to catch systematic issues
  13. Start small (test with 2-3 structures first using --max-compositions 2 --max-structures 2)
  14. Trust PyXtal symmetrization - structures are automatically symmetrized for consistency

Common Workflows

Production Run (Full Scale)

# Step 1: Pre-screening# Option A: Single GPU (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--device cuda \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets >500 compositions)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400
# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Auto-splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor with: squeue -u $USER | grep prescreen# Wait for completion, check and visualize results
cat VASP_JOBS/prescreening_stability.json | jq '.summary'
cat VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'
jq '.results[] | select(.passed_prescreening == true) | {structure_id, energy_above_hull}' VASP_JOBS/prescreening_stability.json
python3 plot_e_above_hull.py --bins 100
# (Optional) Extract stable structures for inspection
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# Step 2: VASP workflow (structures automatically symmetrized with PyXtal)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0 \
--check-interval 120
# Step 3: Analyze electride candidates
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# Step 4: Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# Step 5: Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Step 6: Query and explore
ase db electride_candidates.db
ase db electride_candidates.db 'e_above_hull<0.05' -s space_group_number-

Resume After Interruption

# Check if still running
squeue -u $USER| grep vaspflow_manager
# If stopped, restart - database persists
bash run_workflow.sh --max-concurrent 20

Integration with MatterGen

# 1. Generate structures with MatterGencd~/mattergen_test/ternary_electride
bash generate_ternary_csp.sh
# 2. Transfer to HPC scratchcd /scratch/$USER
cp -r ~/mattergen_test/results/ternary_csp_electrides mattergen_results/
# 3. Run pre-screening (as SLURM job)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Wait for pre-screening to complete
squeue -u $USER| grep prescreen
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 3b. Visualize and extract stable structures (optional)
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 4. Start VASP workflow (as SLURM job)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20
# 5. Monitor and analyze
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# 6. Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# 7. Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# 8. Query candidates
ase db electride_candidates.db 'e_above_hull<0.05'

Credits & References

Credits:

Tools & Libraries:

Key Paper:

@article{zhuComputationalDiscoveryInorganic2019,
title = {Computational {{Discovery}} of {{Inorganic Electrides}} from an {{Automated Screening}}},
author = {Zhu, Qiang and Frolov, Timofey and Choudhary, Kamal},
year = 2019,
month = nov,
journal = {Matter},
volume = {1},
number = {5},
pages = {1293--1303},
issn = {2590-2385},
doi = {10.1016/j.matt.2019.06.017},
}
@misc{tao2026acceleratedinorganicelectridesdiscovery,
title={Accelerated Inorganic Electrides Discovery by Generative Models and Hierarchical Screening}, author={Shuo Tao and Qiang Zhu},
year={2026},
eprint={2601.21077},
archivePrefix={arXiv},
primaryClass={cond-mat.mtrl-sci},
url={https://arxiv.org/abs/2601.21077}, }

About

DFT-HT Workflow for screening inorganic electrides

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

ElectrideFlow - High-Throughput Inorganic Electride Discovery Workflow Accelerated by Generative Models and Hierarchical Prescreening

A four-stage intelligent workflow for high-throughput inorganic electride discovery on HPC clusters:

  1. Chemical Exploration - Generative AI models (MatterGen) explore composition space targeting electride-favorable chemistries
  2. Stability Screening - MatterSim (MLP) pre-screening filters structures by energy above hull before expensive DFT calculations
  3. Electride Identification - Coarse DFT relaxation with ELF & PARCHG topological analysis to identify electride candidates
  4. Refinement - Tight DFT relaxation with refined convex hull analysis for final candidate validation

Table of Contents


Features

MatterSim pre-screening - filter structures by energy_above_hull before VASP (saves 40-60% computation)
Batch processing - reuses MatterSimCalculator across structures for GPU memory efficiency
Parallel prescreening - split prescreening across multiple GPU nodes for faster throughput
Stable phases only - queries only on-hull MP phases for accurate, fast convex hull analysis
Smart caching - single global cache files (mp_mattersim.json, mp_vaspdft.json) handle overlapping systems
PyXtal symmetrization - automatic structure symmetrization for better VASP convergence
Unified SPE workflow - SC-PARCHG-ELF in single job (75% fewer SLURM jobs)
Batch submission - submit n structures at a time, auto-submit more as jobs complete
Dynamic monitoring - check status and submit new jobs automatically
Local JSON database - no network dependencies, works on HPC
Smart workflow - Pre-screen → Relax → SPE (SC + PARCHG + ELF sequential)
PARCHG analysis - band-edge charge density for accurate electride identification
Two-step filtering - initial analysis saves all, stricter filtering for candidates
Fast symmetry - PyXtal-based (14× faster than AFLOW)
Query-able database - ase db commands for candidate exploration
Pymatgen input generation - INCAR, POSCAR, POTCAR, KPOINTS
Bader analysis - identify electride candidates with topological analysis
Interrupt-safe - resume from any interruption
HPC-friendly - workflow manager runs as SLURM job


Quick Start

1. Setup Environment

# On HPC login nodecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# Copy files from your local machine:# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow orchestration# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Monitor workflow progress# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# Load CUDA runtime (check your HPC's available versions, need >= 11.8)
module load cuda/11.8
# Create conda environment
conda create -n mattersim python=3.10
conda activate mattersim
# Install PyTorch with matching CUDA version FIRST# (adjust cu118 to match your loaded CUDA module)
pip install torch==2.5.1+cu118 torchvision==0.20.1+cu118 torchaudio==2.5.1+cu118 \
--index-url https://download.pytorch.org/whl/cu118
pip install torch_scatter==2.1.2+pt25cu118 torch_sparse==0.6.18+pt25cu118 \
torch_cluster==1.6.3+pt25cu118 torch_spline_conv==1.2.2+pt25cu118 \
-f https://data.pyg.org/whl/torch-2.5.1+cu118.html
pip install torch-geometric==2.7.0 pytorch-lightning==2.0.6
# Install pymatgen/mp-api (pinned versions for MP API compatibility)
pip install pymatgen==2024.10.29 mp-api==0.43.0 monty==2024.7.30 emmet-core==0.84.10
# Install other dependencies
pip install numpy>=2.0 ase==3.23.0 pyxtal==1.1.1
# Install MatterSim last (--no-deps to avoid overriding torch versions)
pip install mattersim --no-deps
# Then install any missing mattersim deps that don't conflict:
pip install torch-ema torch-runstats torchmetrics
# Set environment variables in ~/.bashrcecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc

2. Pre-screening with MatterSim (NEW Step)

# Option A: Single GPU job (for small datasets)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--device cuda \
--compositions-per-job 400
# Optional: Add --pure-pbe flag to filter MP entries to pure GGA-PBE only# (default is mixed PBE/PBE+U which is recommended for best accuracy)# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Automatically splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# When done, check results
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# View cache files (single global files with chemsys field)
ls -lh ./VASP_JOBS/mp_mattersim.json
cat ./VASP_JOBS/mp_mattersim.json | jq '.[0]'# (Optional) Visualize results and extract CIF files
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

3. VASP Workflow (Run After Pre-screening)

# Submit VASP workflow manager (processes structures that passed pre-screening)cd /scratch/$USER/vaspflow
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Check job status
squeue -u $USER
tail -f workflow_manager_<JOBID>.out

4. Monitor Progress

cd /scratch/$USER/vaspflow
conda activate mattersim
# Check workflow manager job
squeue -u $USER# View workflow manager log
tail -f workflow_manager_<JOBID>.out
# Overall workflow status
python workflow_status.py ./VASP_JOBS/workflow.json
# Composition breakdown
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# Running VASP jobs
python workflow_status.py ./VASP_JOBS/workflow.json --running
# Failed structures
python workflow_status.py ./VASP_JOBS/workflow.json --failed

5. Analyze Results

# Submit electride analysis as SLURM job
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# When complete, view all analyzed structures
cat electride_analysis.csv
# Filter with stricter criteria to get high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# View filtered candidates
cat electride_candidates.csv
# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Query database for specific criteria
ase db electride_candidates.db 'e_above_hull<0.05'

Complete Setup Guide

Initial Setup (One-time)

# 1. SSH to HPC
ssh your_cluster
# 2. Create conda environment with all dependencies
conda create -n mattersim python=3.10
conda activate mattersim
conda install -c conda-forge pymatgen mp-api
pip install mattersim ase
# 3. Setup workspacecd /scratch/$USER
mkdir -p vaspflow
cd vaspflow
# 4. Upload workflow scripts from your local machine# - prescreen.py # Pre-screening script# - run_prescreen.sh # Submit pre-screening# - submit_prescreen.sh # SLURM script for pre-screening# - plot_e_above_hull.py # Visualize pre-screening results# - extract_stable_structs.py # Extract stable structure CIFs# - workflow_manager.py # VASP workflow# - run_workflow.sh # Submit VASP workflow# - submit_workflow_manager.sh # SLURM script for workflow# - workflow_status.py # Status monitoring# - reset_failed_jobs.py # Reset failed jobs for retry# - Electride.py # Bader analysis# - bader (executable, optional)# 5. Make scripts executable
chmod +x *.py *.sh
# 6. Set environment variablesecho'export PMG_VASP_PSP_DIR=$HOME/apps/PBE64'>>~/.bashrc
echo'export MP_API_KEY=your_materials_project_api_key'>>~/.bashrc
source~/.bashrc
# 7. Verify setup
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
echo"MP API Key: $MP_API_KEY"

Starting a Workflow

# 1. SSH to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# 2. Run pre-screening first (MatterSim + MP)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Monitor pre-screening
squeue -u $USER| grep prescreen
tail -f prescreen_*.out
# Wait for pre-screening to complete (~1-2 hours for 100 structures)# Check results:
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 2b. (Optional) Visualize and extract stable structures
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 3. Submit VASP workflow manager (processes passing structures)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20 \
--max-structures 0
# 4. Monitor (optional)
squeue -u $USER# Check job status
tail -f workflow_manager_*.out # View log# You can now safely log out - workflow runs as SLURM job!

Resuming After Interruption

# SSH back to HPC
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if workflow manager is still running
squeue -u $USER| grep vaspflow_manager
# If not running, resubmit (database persists!)
bash run_workflow.sh --max-concurrent 20
# It automatically resumes from saved state in workflow.json

Workflow Overview

Architecture

MatterGen Structures
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 1: Pre-screening (prescreen.py + MatterSim) │
│ - SLURM job on compute node │
│ - Relax structures with MatterSim ML potential │
│ - Query MP for competing phases (cached per chemical system)│
│ - Compute energy_above_hull │
│ - Output: prescreening_stability.json │
│ - Filter: only E_hull < 0.1 eV/atom proceed to VASP │
└──────────────────────────────────────────────────────────────┘
↓
prescreening_stability.json
↓
┌──────────────────────────────────────────────────────────────┐
│ Step 2: VASP Workflow (workflow_manager.py) │
│ - SLURM job on compute node │
│ - Initialize workflow database (JSON) │
│ - Batch submission loop: │
│ * Submit up to max_concurrent VASP jobs │
│ * Each structure: Relax → SC → PARCHG* → ELF (sequential)│
│ (* PARCHG only for semiconductors, band gap > 0.01 eV) │
│ * Monitor job completion every 60s │
│ * Submit new structures as slots free up │
└──────────────────────────────────────────────────────────────┘
↓
Analyze ELF + PARCHG Results (Bader analysis)
↓
Identify Electride Candidates

Job Chain Per Structure

  1. Pre-screening (MatterSim): Quick stability check → energy_above_hull
  2. Relax (VASP): Optimize geometry → CONTCAR
  3. SC (Self-Consistent): Accurate electronic structure → CHGCAR, WAVECAR, vasprun.xml
  4. PARCHG (all materials): Band-decomposed charge density → PARCHG-band0, PARCHG-band1, PARCHG-e0025, PARCHG-e05, PARCHG-e10
  5. ELF: Calculate electron localization → ELFCAR (PARCHG files copied here for analysis)

Directory Structure

/scratch/$USER/VASP_JOBS/
├── Li10B1N3/
│ ├── Li10B1N3_s001/
│ │ ├── Relax/
│ │ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ │ ├── job.sh
│ │ │ ├── CONTCAR (after completion)
│ │ │ ├── VASP_DONE (or VASP_FAILED)
│ │ │ └── vasp_*.out/err
│ │ └── SPE/ ← Unified SC-PARCHG-ELF directory
│ │ ├── job.sh ← Single SLURM job for all stages
│ │ ├── INCAR, POSCAR, POTCAR, KPOINTS
│ │ ├── generate_parchg_incars.py ← Helper script (copied by workflow)
│ │ ├── SC_DONE, PARCHG_DONE ← Stage markers
│ │ ├── VASP_DONE (or VASP_FAILED) ← Final completion marker
│ │ ├── INCAR-SC, OSZICAR-SC, vasprun.xml-SC ← SC outputs
│ │ ├── INCAR-PARCHG-e0025, INCAR-PARCHG-e05, INCAR-PARCHG-e10
│ │ ├── INCAR-PARCHG-band0, INCAR-PARCHG-band1
│ │ ├── PARCHG.tar.gz ← Compressed PARCHG files
│ │ ├── INCAR-ELF
│ │ ├── ELFCAR ← ELF output
│ │ ├── ELF_DONE ← ELF stage marker
│ │ └── vasp_*.out/err
│ └── Li10B1N3_s002/
├── workflow.json # Job tracking database
├── prescreening_stability.json ← Pre-screening results
├── mp_mattersim.json ← Cached MP stable phases (MatterSim energies)
├── mp_vaspdft.json ← Cached MP stable phases (DFT energies)
└── electride_candidates.json # Analysis results

Workflow States

Each structure progresses through these states in workflow_manager.py:

PENDING (structure passed pre-screening, ready for VASP)
↓
RELAX_RUNNING → RELAX_DONE → SC_RUNNING → PARCHG_RUNNING → ELF_RUNNING → ELF_DONE
↓ ↓ ↓ ↓ ↓ ↓
RELAX_FAILED (skip) SC_FAILED PARCHG_FAILED ELF_FAILED (success)
Note: SC_RUNNING, PARCHG_RUNNING, and ELF_RUNNING are all part of one SPE job
State transitions happen automatically as stage markers are detected

Note: Pre-screening (MatterSim + MP hull analysis) is done separately by prescreen.py. Only structures that pass pre-screening (E_hull < threshold) are loaded into workflow_manager.py.

Key behaviors:

  • Only structures that passed pre-screening are processed
  • Reduced SLURM jobs: 2 jobs per structure (1 Relax + 1 SPE) instead of 8 jobs
  • SPE job runs sequentially: SC -> PARCHG (5 energy windows) -> ELF in one script
  • Stage markers: SC_DONE, PARCHG_DONE, VASP_DONE track progress within SPE job
  • State transitions: Workflow manager detects markers and transitions states automatically
  • PARCHG for ALL materials: Following HT-electride methodology
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied)
  • Workflow manager automatically submits next structure when slots free up
  • Failed jobs don't block other structures
  • Max concurrent limit applies to total running structures

SPE Workflow Architecture

The unified SPE (SC-PARCHG-ELF) workflow uses a clean separation of concerns:

Python (workflow_manager.py) handles:

  • INCAR/POSCAR/POTCAR/KPOINTS for Relax, SC, ELF jobs
  • Structure loading from CIF files and symmetrization
  • Database state tracking and job orchestration
  • Directory structure creation

Helper script (generate_parchg_incars.py) handles:

  • PARCHG INCAR generation (requires parsing vasprun.xml-SC)
  • Band index calculation from NELECT and SOC parameters
  • FFT grid extraction (NGXF, NGYF, NGZF)
  • Called from bash after SC completes

Bash (job.sh in SPE/) handles:

  • Sequential execution: SC → PARCHG (5 types) → ELF
  • File copying between stages (CHGCAR-SC, WAVECAR-SC reused)
  • PARCHG output renaming (PARCHG → PARCHG-e0025, etc.)
  • PARCHG compression (PARCHG-* → PARCHG.tar.gz) to save disk space
  • Cleanup between stages to prevent VASP issues
  • Stage marker creation (SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE)

Why this design:

  • PARCHG is the ONLY calculation requiring runtime VASP output parsing
  • Keeps Python code IDE-friendly (no embedded heredocs)
  • Helper script is testable standalone
  • Other INCARs are straightforward pymatgen calls (no external scripts needed)

Monitoring

Option 1: Workflow Status Tool (Recommended)

# Overall summary
python workflow_status.py ./VASP_JOBS/workflow.json

Shows:

  • Total structures
  • Status breakdown (PENDING, RELAX_RUNNING, SC_RUNNING, etc.)
  • Currently running count
  • Completion percentage

Additional views:

# Running jobs with SLURM job IDs
python workflow_status.py workflow.json --running
# Failed structures (for debugging)
python workflow_status.py workflow.json --failed
# Composition-level summary
python workflow_status.py workflow.json --compositions
# Recently completed structures
python workflow_status.py workflow.json --completed --limit 20
# Filter by specific state
python workflow_status.py workflow.json --details --state SC_RUNNING

Option 2: Reattach to Tmux

# See live workflow output
tmux attach -t vaspflow
# View, then detach: Ctrl+B, then D

Option 3: Check SLURM Queue

# Check running jobs
squeue -u $USER# Check job history
sacct -S $(date --date="7 days ago" -I) -u $USER# Detailed job info
scontrol show job <JOBID>

Option 4: Manual Inspection

# View database directly
cat ./VASP_JOBS/workflow.json | jq '.structures | to_entries | map({id: .key, state: .value.state})'# Check specific job directorycd ./VASP_JOBS/Li10B1N3/Li10B1N3_s001/Relax
ls -lh
tail vasp_*.out
tail OSZICAR

Analyzing Results for Electride Candidates

After ELF calculations complete, analyze structures for electride characteristics using Bader topological analysis on both ELFCAR and PARCHG files.

New in v2.0: Incremental analysis with MatterSim e_above_hull integration, PyXtal database storage, and stricter candidate filtering.

Step 1: Initial Analysis (All Structures)

Recommended: Run analysis as a SLURM job (not on login node):

# Submit analysis job with defaults
bash submit_analysis.sh
# Custom settings
bash submit_analysis.sh \
--vasp-jobs ./VASP_JOBS \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv
# Monitor analysis job
squeue -u $USER| grep analyze
tail -f electride_analysis_*.out
# View results when complete
cat electride_analysis.csv

Output:

  • electride_analysis.csv - All analyzed structures with interstitial volumes
  • electride_data.db - PyXtal database with all structures

Step 2: Filter High-Quality Candidates

Apply stricter volume thresholds to identify high-quality electride candidates:

# Filter with default thresholds (20 ų)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# Custom thresholds (stricter)
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 25 \
--min-band 25

Filtering Criteria:

  • max(e0025, e05, e10) >= min-energy (default: 20 ų)
  • max(band0, band1) >= min-band (default: 20 ų)
  • Removes duplicate structures
  • Adds PyXtal symmetry information (space groups)

Output:

  • electride_candidates.db - Filtered high-quality candidates with symmetry
  • electride_candidates.csv - CSV table for quick viewing

Step 3: Extract CIF Files

Extract CIF files for the filtered candidates:

# Extract from filtered database
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Output: electride_CIF/*.cif - One CIF file per candidate

Step 4: Query Database

Use ase db to query and filter candidates:

# View all candidates
ase db electride_candidates.db
# Sort by space group (high symmetry first)
ase db electride_candidates.db \
formula,space_group_number,e_above_hull \
-s space_group_number-
# Filter by stability (< 50 meV/atom)
ase db electride_candidates.db 'e_above_hull<0.05'# Show interstitial volumes
ase db electride_candidates.db \
formula,e0025,e05,e10,band0,band1,e_above_hull
# Cubic structures (space group >= 195)
ase db electride_candidates.db 'space_group_number>=195'# High interstitial volume (e0025 > 50 ų)
ase db electride_candidates.db 'e0025>50'

What the Analysis Does

Initial Analysis (analyze.py):

  1. Reads ELFCAR - electron localization function from VASP SPE directory
  2. Extracts PARCHG files from PARCHG.tar.gz (5 types):
    • PARCHG-band0: Valence band maximum (VBM)
    • PARCHG-band1: Second highest occupied band (VBM-1)
    • PARCHG-e0025: Energy window [-0.025, 0.025] eV around Fermi level
    • PARCHG-e05: Energy window [-0.5, 0.025] eV
    • PARCHG-e10: Energy window [-1.0, 0.025] eV
  3. Runs Bader analysis on ELFCAR and each PARCHG file
  4. Filters interstitial electrons - sites far from atoms with high localization
  5. Reports volumes of interstitial electron density (ų) for each type
  6. Adds stability data - reads e_above_hull from prescreening_stability.json
  7. Extracts spacegroup - from CONTCAR using PyXtal (adaptive tolerance)
  8. Saves to database - stores all structures in electride_data.db

Filtering (filter_comb_db.py):

  1. Applies volume thresholds - only keeps structures with substantial interstitial volumes
  2. Symmetrizes structures - uses PyXtal with adaptive tolerance (coarse→fine)
  3. Removes duplicates - identifies and filters redundant structures
  4. Adds space group info - from PyXtal symmetry analysis
  5. Creates unified database - electride_candidates.db with structures + volumes
  6. Exports CSV - electride_candidates.csv for quick viewing

Key Features (v2.0)

Incremental Analysis:

  • Automatically skips already-analyzed structures from CSV and database
  • Run repeatedly as new ELF calculations complete without re-processing
  • Perfect for monitoring ongoing workflows

Enhanced Electride Criteria:

  • Old criteria: ANY of (e0025 > 0 OR e05 > 0 OR e10 > 0 OR band0 > 0)
  • New criteria: ALL of (e0025 > 0 AND e05 > 0 AND e10 > 0 AND band0 > 0)
  • More stringent to reduce false positives

DFT Integration:

  • Reads DFT energy_above_hull from compute_dft_e_hull.py output
  • Results sorted by stability (lowest e_above_hull first)
  • Most stable electride candidates rise to the top

PyXtal Database:

  • Saves all analyzed structures to electride_data.db
  • Adaptive symmetrization (tolerances: 1e-5 to 0.5)
  • P1 fallback ensures 100% save success
  • Query-able for advanced analysis

Analysis Parameters

analyze.py:

  • --threshold: Minimum ELF value for electride detection (default: 0.6)
  • --bader-exe: Path to Bader executable (default: bader in PATH)
  • --output: Output CSV file name (default: electride_analysis.csv)
  • --pyxtal-db: PyXtal database file (default: electride_data.db)
  • --prescreening: MatterSim stability JSON (default: ./VASP_JOBS/prescreening_stability.json)
  • --workers: Number of parallel workers (default: CPU count)

filter_comb_db.py:

  • --min-energy: Minimum for max(e0025, e05, e10) in ų (default: 20)
  • --min-band: Minimum for max(band0, band1) in ų (default: 20)
  • --output: Output database (default: electride_candidates.db)
  • --output-csv: Output CSV (default: electride_candidates.csv)

Understanding Results

Initial Analysis (electride_analysis.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045
Li10B1N4_s003,Li10B1N4,0.00,0.00,0.00,5.28,0.00,12,0.068

Columns:

  • formula: Structure ID
  • composition: Chemical formula
  • e0025, e05, e10: Interstitial volumes (ų) from energy windows
  • band0, band1: Interstitial volumes (ų) from band-specific charges
  • spacegroup: PyXtal space group (1 = P1 fallback)
  • e_above_hull: MatterSim energy above hull (eV/atom)

Electride Criteria:

  • (e0025 > 0 OR e05 > 0) AND (e10 > 0 OR band0 > 0)

Filtered Candidates (electride_candidates.csv):

formula,composition,e0025,e05,e10,band0,band1,spacegroup,e_above_hull
Li10B1N4_s001,Li10B1N4,32.62,31.82,31.31,35.11,0.00,166,0.023
Li10B1N4_s002,Li10B1N4,15.23,12.45,18.67,22.34,0.00,139,0.045

Additional Filtering:

  • max(e0025, e05, e10) >= 20 ų (substantial energy window volume)
  • max(band0, band1) >= 20 ų (substantial band-specific volume)
  • Duplicates removed
  • Space group from PyXtal symmetry analysis

Interpreting volumes (in ų):

  • > 20: High-quality electride (passes filtering)
  • 0-20: Weak electride (filtered out by default)
  • High across multiple columns: Strong, robust electride character

Example interpretation:

  • Li10B1N4_s001: High-quality electride (all volumes > 20 ų, stable)
  • Li10B1N4_s002: Moderate electride (volumes > 12 ų, borderline)
  • Li10B1N4_s003: Not electride (very low volumes)

Sorting:

  • Both CSVs sorted by e_above_hull (low → high)
  • Most thermodynamically stable candidates appear first

Console output during analysis:

Total ELF_DONE: 100
Semiconductors (with PARCHG): 15
Metals (ELFCAR only): 85
(All structures analyzed with PARCHG in SPE workflow)
Analyzing: Li10B1N4_s001 (VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE)
Spacegroup: 166
*** ELECTRIDE CANDIDATE *** (e0025=32.62, e05=31.82, e10=31.31, band0=35.11, band1=0.00)
Analyzing: Li10B1N4_s003 (VASP_JOBS/Li10B1N4/Li10B1N4_s003/SPE)
Spacegroup: 139
Not electride (e0025=0.00, e05=0.00, e10=0.00, band0=5.28, band1=0.00)

Filter output:

======================================================================
Filtering Electride Database with Stricter Criteria
======================================================================
Criteria:
max(e0025, e05, e10) >= 20.0 ų
max(band0, band1) >= 20.0 ų
Processing structures...
Added 100 structures...
Using P1 fallback for Ba8S7_s024
Added 200 structures...
Filtering Summary:
Input structures: 6134
Filtered out (below thresholds): 4512
Duplicates removed: 89
Failed to process: 0
Added to output database: 1533

Incremental Analysis Workflow

# Day 1: 50 ELF calculations done
bash submit_analysis.sh
# Output: 50 structures analyzed# → electride_analysis.csv (50 structures)# → electride_data.db (50 structures)# Filter to get high-quality candidates
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 25 high-quality)# electride_candidates.csv# Day 2: 30 more ELF calculations done (total 80)
bash submit_analysis.sh
# Output: Only 30 new analyzed (skips existing 50)# → electride_analysis.csv updated (80 total, re-sorted)# → electride_data.db updated (80 total)# Re-filter with updated data
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: electride_candidates.db (e.g., 40 high-quality)# Day 3: 20 more ELF calculations done (total 100)
bash submit_analysis.sh
# Output: Only 20 new analyzed# → Final electride_analysis.csv (100 structures)# Final filtering
python3 filter_comb_db.py --input electride_data.db --csv electride_analysis.csv
# Output: Final electride_candidates.db (e.g., 50 high-quality)# Extract CIF files for candidates
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF

Benefits:

  • Incremental analysis saves time (only analyzes new structures)
  • Filtering is fast (~2 min) and can be adjusted without re-running Bader
  • Database is query-able at any stage

Direct Analysis (Advanced)

The analysis uses Electride.py internally via analyze.py. For manual testing:

# Test on single structure (SPE workflow)cd VASP_JOBS/Li10B1N4/Li10B1N4_s001/SPE
python3 ../../../../Electride.py . --bader-exe ~/apps/Bader/bader
# Run full analysis with all options
python3 analyze.py \
--db VASP_JOBS/workflow.json \
--bader-exe ~/apps/Bader/bader \
--threshold 0.6 \
--output electride_analysis.csv \
--pyxtal-db electride_data.db \
--prescreening VASP_JOBS/prescreening_stability.json \
--workers 32
# Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20

Requirements:

  • ELFCAR file (generated by VASP with LELF=True in SPE/)
  • PARCHG.tar.gz (5 files compressed, automatically extracted during analysis)
  • Bader executable (download from: https://theory.cm.utexas.edu/henkelman/code/bader/)
  • (Optional) prescreening_stability.json for MatterSim e_above_hull values

Output Files

Initial Analysis:

  1. electride_analysis.csv: All analyzed structures with volumes
  2. electride_data.db: PyXtal database with all structures
  3. electride_analysis_detailed.log: Full console output

Filtered Candidates:

  1. electride_candidates.csv: High-quality candidates (CSV table)
  2. electride_candidates.db: PyXtal database with filtered structures + volumes
  3. electride_CIF/: Directory with CIF files for candidates

Performance

Analysis (analyze.py):

  • Incremental mode: Only analyzes new structures (minutes for 30 new structures)
  • Full analysis: ~5-10 minutes per structure (PARCHG extraction + Bader analysis)
  • Database saves: ~1 second per structure (with adaptive tolerance)
  • Parallel processing: Scales with CPU cores (32 cores recommended)

Filtering (filter_comb_db.py):

  • Time: ~2 minutes for 6000 structures
  • PyXtal symmetry: ~0.02 sec per structure (vs AFLOW: ~0.45 sec)
  • Speedup: 14× faster than AFLOW-based workflow
  • Duplicate removal: Automatic during processing

DFT Energy Above Hull Calculation

After VASP relaxations complete, compute DFT-level thermodynamic stability using your VASP energies combined with Materials Project DFT energies for competing phases.

Energy Method Comparison

Compare energies between different calculation methods to validate pre-screening accuracy and diagnose any systematic biases:

# Run comparison (requires dft_stability_results.json)
bash run_compare_energy_method.sh \
--vasp-jobs ./VASP_JOBS \
--outlier-threshold 0.5
# Monitor job
squeue -u $USER| grep compare_energy
tail -f compare_energy_method_*.out
# Results will be in: VASP_JOBS/energy_method_comparison.json# Plots: mp_phases_comparison_*.png, generated_structures_comparison_*.png

What it compares:

  1. MP On-Hull Phases: MatterSim energies vs MP raw DFT energies
  2. Generated Structures: MatterSim energies vs VASP-DFT energies

Important: The generated structures comparison now uses dft_stability_results.json as the single source of truth for VASP energies. This ensures exact consistency with hull_comparison plots (same structures, same outlier filtering).

Key metrics:

  • Pearson correlation between methods
  • Mean Absolute Error (MAE)
  • Systematic bias detection
  • Helps diagnose non-linear hull behavior

Usage

# Submit DFT hull calculation (after VASP relaxations complete)
bash run_dft_e_hull.sh \
--vasp-jobs ./VASP_JOBS \
--output dft_stability_results.json \
--prescreen-results ./VASP_JOBS/prescreening_stability.json
# Monitor job
squeue -u $USER| grep dft_e_hull
tail -f dft_e_hull_*.out
# Hull comparison (MatterSim vs DFT) is automatically generated# if --prescreen-results is provided to compute_dft_e_hull.py# Results will be in: VASP_JOBS/hull_comparison.json# Plots: hull_comparison_scatter.png, hull_comparison_residuals.png

What It Does

  1. Scans for completed VASP relaxations (RELAX_DONE or later states)
  2. Extracts VASP energies from vasprun.xml
  3. Queries MP for stable phases only (is_stable=True) - much faster than querying all phases
  4. Uses single cache file (mp_vaspdft.json) with automatic subsystem handling
  5. Computes DFT energy_above_hull for each structure using PDEntry
  6. Outputsdft_stability_results.json with decomposition products

Output Format

{
"summary": {
"total_structures": 100,
"processed_successfully": 95,
"failed": 5,
"energy_reference": "DFT uncorrected (VASP-PBE + MP stable phases only)",
"mp_phase_selection": "stable_only (is_stable=True)",
"mp_functional_filter": "mixed_pbe_pbeU"
},
"results": [
{
"structure_id": "Li10B1N4_s001",
"composition": "Li10B1N4",
"chemsys": "B-Li-N",
"vasp_energy_per_atom": -3.45678,
"dft_energy_above_hull": 0.023,
"decomposition_products": "Li3N (0.714) + BN (0.286)",
"num_mp_stable_phases": 18,
"error": null
}
]
}

Validation: MatterSim vs DFT Hull Comparison

The compute_dft_e_hull.py script automatically validates pre-screening accuracy by comparing MatterSim vs DFT hull values when --prescreen-results is provided:

Statistical metrics:

  • Pearson correlation (how well MatterSim predicts DFT)
  • Mean Absolute Error (MAE)
  • Root Mean Square Error (RMSE)

Pre-screening performance:

  • True Positives: Correctly passed (stable in both)
  • False Positives: Incorrectly passed (unstable in DFT, wasted VASP)
  • True Negatives: Correctly filtered (unstable in both)
  • False Negatives: Incorrectly filtered (stable in DFT, missed!)
  • Precision, Recall, F1 Score
  • Computational savings (% VASP avoided)

Output: hull_comparison.json with detailed analysis

When to Use

  • After some VASP relaxations complete: Validate pre-screening accuracy early
  • Before publication: Get accurate DFT stability data
  • To identify outliers: Find structures that were incorrectly filtered/passed

Performance

  • Time: ~1-2 hours for 100 structures (mostly MP API queries)
  • Resources: 8 CPUs, 32GB RAM (for large systems)
  • Caching: Uses MP IDs from pre-screening cache to minimize API calls

Troubleshooting

Workflow Manager Not Running

Symptom: Jobs complete but database still shows RUNNING state

Check if manager job is running:

squeue -u $USER| grep vaspflow_manager

Solution: Restart workflow manager if stopped

bash run_workflow.sh --max-concurrent 10
# It will detect completed jobs and update states

Jobs Not Progressing

Check:

# Check workflow manager job
squeue -u $USER| grep vaspflow_manager
tail -f workflow_manager_*.out
# See what's completed
find ./VASP_JOBS -name "VASP_DONE"| wc -l
find ./VASP_JOBS -name "VASP_FAILED"| wc -l
# Check VASP jobs in queue
squeue -u $USER# Check database state
python workflow_status.py ./VASP_JOBS/workflow.json

Fix: Restart workflow manager if it stopped

bash run_workflow.sh --max-concurrent 10

Failed Jobs

# List all failures
python workflow_status.py workflow.json --failed
# Investigate specific failurecd ./VASP_JOBS/Li10B1N3/Li10B1N3_s003/Relax
tail -50 vasp_*.err
tail -50 OSZICAR
grep -i "error\|killed\|fail" vasp_*.out

Common failure causes:

  • Walltime limit hit (24 hours default)
  • Convergence issues (check OSZICAR)
  • Memory issues (check vasp_*.err)
  • POTCAR problems (check first few lines of vasp_*.out)

Resetting Failed Jobs for Retry

Use reset_failed_jobs.py to reset failed structures and retry them:

# Step 1: List all failed structures to understand what went wrong
python3 reset_failed_jobs.py --list
# Output shows failures grouped by stage:# RELAX_FAILED: 72 structures# SC_FAILED: 4 structures# PARCHG_FAILED: 4 structures# Step 2: Dry run to preview changes (recommended)
python3 reset_failed_jobs.py --dry-run --clean
# Step 3: Reset all failed jobs
python3 reset_failed_jobs.py --clean
# OR reset specific stage only
python3 reset_failed_jobs.py --stage RELAX --clean
python3 reset_failed_jobs.py --stage SC --clean
python3 reset_failed_jobs.py --stage PARCHG --clean
# Step 4: Resume workflow to retry
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10

What it does:

  • RELAX_FAILEDPENDING (retry from scratch)
  • SC_FAILEDRELAX_DONE (retry SC using existing relaxed structure)
  • PARCHG_FAILEDSC_DONE (retry PARCHG using existing SC results)
  • --clean flag removes VASP_FAILED markers for clean restart
  • Creates automatic backup: workflow.json.bak

Important: Investigate failure causes before blindly retrying. Some structures may have fundamental issues (bad geometry, unconverged, etc.) and will fail repeatedly.

POTCAR Not Found

# Check environmentecho$PMG_VASP_PSP_DIR# Verify structure
ls $PMG_VASP_PSP_DIR/POT_GGA_PAW_PBE/Li/POTCAR
# Set if neededexport PMG_VASP_PSP_DIR=$HOME/apps/PBE64
# Add to ~/.bashrc to persist

Workflow Manager Job Issues

# Check if manager job is running
squeue -u $USER| grep vaspflow_manager
# View manager log
tail -100 workflow_manager_*.out
# Cancel stuck manager job
scancel <JOBID># Restart (database persists!)
bash run_workflow.sh --max-concurrent 10

Jobs Stuck in SLURM Queue

# Check job status
squeue -u $USER -o "%.18i %.9P %.30j %.8T %.10M %.6D %R"# Check why pending
squeue -u $USER -j <JOBID> --start
# Cancel stuck job if needed
scancel <JOBID># Workflow will mark it as failed on next check

Database Corruption

# Backup database
cp workflow.json workflow.json.backup
# Reinitialize (keeps existing directories)
python workflow_manager.py --init-only \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS
# Manually merge completed jobs from backup if needed

Parallel Pre-screening Results Missing

Symptom: After running submit_parallel_prescreen.sh, the prescreening_stability.json file is empty or only contains results from one batch.

Cause: Multiple parallel jobs writing to the same file cause race conditions and data loss.

Solution:

  1. Each batch processes a different subset of compositions using --start-composition (batch 0: comps 0-399, batch 1: 400-799, etc.)
  2. Each batch writes to its own file (prescreening_stability_batch0.json, etc.)
  3. After all jobs complete, merge them with merge_prescreen_batches.py:
# Check that all batch jobs completed
squeue -u $USER| grep prescreen # Should be empty# List batch result files
ls ./VASP_JOBS/prescreening_stability_batch*.json
ls ./VASP_JOBS/prescreening_structures_batch*.db
ls ./VASP_JOBS/mp_mattersim.json # Shared cache (not batch-specific)# Merge all batch results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# OR skip database merge (faster, JSON only)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS --skip-database
# Verify merged results
cat ./VASP_JOBS/prescreening_stability.json | jq '.metadata.total_structures'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Check shared MP cache
ls -lh ./VASP_JOBS/prescreening_structures.db # Check database exists

Prevention: Always run merge_prescreen_batches.py after parallel prescreening jobs complete.


Configuration

Key Parameters

Pre-screening (prescreen.py):

# Single GPU job
python prescreen.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0 \ # Max structures per composition
--batch-size 32 \ # Structures per batch (calculator reuse)
--mp-api-key YOUR_KEY \ # Materials Project API key
--hull-threshold 0.05 \ # E_hull threshold (eV/atom)
--device cuda \ # MatterSim device: cpu or cuda
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Filter MP to pure GGA-PBE only (exclude PBE+U)# Automatically splits compositions across GPU nodes

VASP Workflow (workflow_manager.py):

python workflow_manager.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \ # Max structures running simultaneously
--max-compositions 20 \ # Limit number of compositions (optional)
--max-structures 0 \ # Max structures per composition
--check-interval 60 # Status check interval (seconds)

Recommendations:

  • Pre-screening:
    • --batch-size: 32 for A40/A100 GPUs (48GB VRAM), reduce to 16 for smaller GPUs
    • --hull-threshold: 0.1 eV/atom filters most unstable structures, use 0.05 for stricter filtering
    • --device: Use cuda for GPU acceleration (5-10× faster than CPU)
    • --mp-api-key: Get your free API key at https://next-gen.materialsproject.org/api
    • --pure-pbe: OPTIONAL flag to exclude PBE+U (recommended to OMIT for best accuracy)
      • Default (no flag): Mixed PBE/PBE+U (matches MP phase diagram methodology)
      • With flag: Pure GGA-PBE only (may reduce accuracy for transition metal systems)
    • MP API: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • Large datasets: Use submit_parallel_prescreen.sh to split across multiple GPUs
    • GPU memory: Set export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True in SLURM script
  • VASP Workflow:
  • --max-concurrent: 10-20 for typical HPC cluster
  • --check-interval: 60s is good balance
  • --max-compositions: Omit to process all
    • PyXtal: Structures automatically symmetrized for better convergence

SLURM Settings

Edit create_slurm_script() in workflow_manager.py (lines 163-176):

script=f"""#!/bin/bash#SBATCH --partition=Apus # Change partition#SBATCH --ntasks=32 # Change cores#SBATCH --time=1-00:00:00 # Change walltime (1 day)#SBATCH --mem=64G # Change memoery#SBATCH --output={job_dir}/vasp_%j.out#SBATCH --error={job_dir}/vasp_%j.err

VASP Input Settings

Edit create_vasp_inputs() in workflow_manager.py (lines 129-161):

Relax (line 135-142):

vis=MPRelaxSet(structure, user_incar_settings={
'EDIFF': 1e-6, # Energy convergence'EDIFFG': -0.01, # Force convergence (eV/Å)'NSW': 200, # Max ionic steps'PREC': 'Accurate',
'ISMEAR': 0, # Gaussian smearing'SIGMA': 0.05,
})

SC/Static (line 143-148):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LAECHG': True, # Write core charge'LCHARG': True, # Write CHGCAR
})

ELF (line 149-156):

vis=MPStaticSet(structure, user_incar_settings={
'PREC': 'Accurate',
'LELF': True, # Calculate ELF'ADDGRID': True, # Finer FFT grid'NSW': 0, # No ionic steps'IBRION': -1,
})

Electride Detection Parameters

python analyze_completed.py \
--threshold 0.6 \ # ELF threshold (0.5-0.7 typical)
--min-distance 1.5 \ # Min distance from atoms (Å)
--volume-threshold 0.5 # Min interstitial volume (ų)

Performance

Per Structure (typical, 32 cores)

Pre-screening (MatterSim):

  • Relaxation: 10-30s per structure (CPU) or 5-10s (GPU)
  • MP query: One-time per chemical system (~2-5 min, cached)
  • Hull analysis: <1s per structure

VASP calculations:

  • Relax: 2-6 hours
  • SPE job (SC + PARCHG + ELF sequential): 5-10 hours
    • SC: 1-3 hours
    • PARCHG (5 sequential): 2.5-5 hours (5 × 30-60 min)
    • ELF: 1-2 hours
  • Total VASP time: 7-16 hours/structure
  • SLURM overhead: Reduced by 75% (2 jobs instead of 8 jobs per structure)

With pre-screening (filters ~60% structures):

  • Effective time: 3-6 hours/structure (accounting for filtered structures)
  • Savings: 40-60% of total VASP computation time

Example Workflow (100 structures, max_concurrent=10, with pre-screening)

TimeActionRunningCompletedNotes
T=0Pre-screen 100 structures00MatterSim + MP
T=1hPre-screening done0060 pass, 40 filtered out
T=1hSubmit first 10 Relax jobs100Only stable structures
T=5h10 Relax done, submit 10 SPE100SPE = SC+PARCHG+ELF
T=13h10 SPE done, submit new1010~8h per SPE job
...Repeat10...
T=53hAll 60 complete06040 filtered by pre-screening

Wall time: ~53 hours for 100 structures (60 pass pre-screening)
Core-hours: ~24,000 (60 structures × 12.5h avg × 32 cores / 2 efficiency)
SLURM jobs: 120 total (vs 480 with old workflow)
Savings: 40-60% computational time from pre-screening, 75% fewer SLURM jobs


MatterSim Pre-screening

Pre-screening uses the MatterSim ML potential to quickly evaluate thermodynamic stability before running expensive VASP calculations. This is done in a separate step using prescreen.py, which generates prescreening_stability.json with structures that pass the stability threshold.

How It Works

  1. MatterSim Relaxation: Structures relaxed in batches with calculator reuse for GPU memory efficiency
  2. MP Reference Phases Query: Uses legacy pymatgen.ext.matproj.MPRester for complete GGA coverage
    • The modern mp_api.client misses many stable GGA phases needed for accurate hull calculations
    • Strict filtering: only accepts entries with -GGA or -GGA+U suffix in entry_id
    • Uses uncorrected_energy (raw DFT, no MP corrections) to match MatterSim energies
    • Optional --pure-pbe flag to exclude PBE+U (use pure GGA-PBE only)
  3. Re-relax MP Structures: MP GGA structures are re-relaxed with MatterSim for consistent energy reference
  4. Convex Hull: Build phase diagram using MatterSim energies with PDEntry
  5. Output: Generate prescreening_stability.json with structures that pass threshold
  6. VASP Workflow Filter: workflow_manager.py reads prescreening_stability.json and only processes structures with E_hull < threshold (default: 0.1 eV/atom)

Key Optimizations (NEW)

Batch Processing:

  • MatterSimCalculator reused across 32 structures per batch (configurable with --batch-size)
  • Dramatically reduces GPU memory overhead and initialization time
  • Automatic GPU memory cleanup between batches
  • Supports CUDA memory expansion: PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

Complete GGA Coverage with Legacy API:

  • Uses legacy pymatgen.ext.matproj.MPRester instead of modern mp_api.client
  • Modern API misses many stable GGA phases critical for accurate hull calculations
  • Queries ALL GGA/GGA+U entries via get_entries_in_chemsys()
  • Strict suffix filtering: Only accepts entries with -GGA or -GGA+U suffix in entry_id
  • Excludes r2SCAN, SCAN, and entries without explicit functional suffix
  • Uses uncorrected_energy (raw DFT, no MP anion/composition corrections)
  • Optional --pure-pbe flag to exclude PBE+U (for pure GGA-PBE calculations only)
  • More accurate phase diagrams with comprehensive GGA reference phases

Single Global Cache Files:

  • mp_mattersim.json: All MatterSim-relaxed MP phases with chemsys field
  • mp_vaspdft.json: All MP DFT energies with chemsys field
  • Automatically handles overlapping chemical systems (e.g., B-Li-N includes B, Li, N subsystems)
  • No more separate cache directories with duplicate data

Parallel Multi-GPU Processing:

  • submit_parallel_prescreen.sh: Splits compositions across multiple GPU nodes
  • Each batch job writes to unique files:
    • JSON: prescreening_stability_batch0.json, prescreening_stability_batch1.json, ...
    • Database: prescreening_structures_batch0.db, prescreening_structures_batch1.db, ...
  • MP cache is SHARED across all batches using dual-level file locking:
    • Single file: mp_mattersim.json (all batches read/write safely)
    • Cache I/O locking: mp_mattersim.lock prevents file corruption
    • Per-chemsys locking: mp_cache_{chemsys}.lock prevents duplicate MP queries
    • When Batch 0 queries Ba-O, other batches wait for it to finish
    • After Batch 0 completes, other batches read from cache (no duplicate API calls)
    • Lock files auto-cleaned after merge
  • After all jobs complete, run merge_prescreen_batches.py to combine results
  • Command-line configurable (use --help for full options)
  • Configurable compositions per job (default: 400)
  • Linear speedup with number of GPUs
  • Example: 2000 compositions → 5 GPU nodes = 5x faster
  • Critical: File locking ensures safe concurrent access to shared MP cache

PyXtal Symmetrization:

  • Structures automatically symmetrized before MatterSim relaxation
  • Same symmetrization applied to VASP initial structures in workflow_manager.py
  • Improves convergence and consistency between pre-screening and VASP

Configuration

# Option A: Single GPU job (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--device cuda \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400 \
--pure-pbe # OPTIONAL: Pure GGA-PBE only (omit for best accuracy)# View all options
bash submit_parallel_prescreen.sh --help
# Monitor parallel jobs
squeue -u $USER| grep prescreen
# After all parallel jobs complete, merge batch results
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# This combines:# - prescreening_stability_batch*.json → prescreening_stability.json# - prescreening_structures_batch*.db → prescreening_structures.db# - mp_mattersim.json is already shared (no merging needed)# Options:# --keep-batches: preserve individual batch files (default: delete after merge)# --skip-database: skip database merge, only merge JSON (faster)# Custom options for single GPU
bash run_prescreen.sh \
--batch-size 64 \ # Larger batch (requires more GPU memory)
--hull-threshold 0.05 \ # Stricter threshold (fewer pass)
--device cuda # Use GPU (much faster than CPU)# Check results and cache
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'
cat ./VASP_JOBS/mp_mattersim.json | jq 'length'# Number of cached MP phases
cat ./VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'# By chemical system# Step 2: Run VASP workflow (automatically filters based on pre-screening)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0
# Note: VASP structures are automatically symmetrized with PyXtal before relaxation# This ensures consistency with pre-screening and improves convergence# By default, workflow_manager.py looks for:# ./VASP_JOBS/prescreening_stability.json## To use a different file:
bash run_workflow.sh --prescreen-results /path/to/custom_results.json
# To skip filtering (process all structures):# (Not recommended - remove prescreening_stability.json first)
bash run_workflow.sh # Will warn if file not found

Performance Impact

Overhead (with optimizations):

  • Single GPU: ~30-60 minutes for 100 structures across 10 chemical systems
  • Parallel (5 GPUs): ~10-15 minutes for same dataset (5x speedup)
  • Batch processing: 3-5x faster than previous per-structure calculator creation
  • Stable phases only: 10-20x faster MP queries (20-50 phases vs 500+ phases)
  • First structure in each chemical system takes longer (MP query + cache)
  • Subsequent structures in same system benefit from shared cache

Cache Efficiency:

  • Single mp_mattersim.json file (~1-5 MB) replaces multiple per-chemsys files
  • Automatic deduplication of overlapping subsystems
  • B-Li-N system includes: B, Li, N, B-Li, B-N, Li-N, B-Li-N (7 subsystems in 1 cache)

Savings:

  • Filters 50-80% of structures (typical)
  • Saves 4-10 VASP hours per filtered structure
  • Net savings: 40-60% of total computation time
  • Additional: Pre-screening itself is 3-5x faster with batch processing

Checking Pre-screening Results

# View pre-screening summary
cat VASP_JOBS/prescreening_stability.json | jq '.summary'# View individual results
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | { id: .structure_id, chemsys: .chemsys, E_hull: .energy_above_hull, passed: .passed_prescreening}'| less
# Count passed vs filtered
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==true)'| jq -s 'length'
cat VASP_JOBS/prescreening_stability.json | jq '.results[] | select(.passed_prescreening==false)'| jq -s 'length'

Pre-screening Utilities

Visualizing Energy Distribution

Use plot_e_above_hull.py to visualize the energy distribution and verify your threshold:

# Plot histogram of energy_above_hull values
python3 plot_e_above_hull.py \
--input ./VASP_JOBS/prescreening_stability.json \
--output histogram.png \
--bins 100 \
--max-energy 2.0

Extracting Stable Structures

Use extract_stable_structs.py to extract CIF files for structures that passed pre-screening:

# Extract CIF files for structures that passed pre-screening
python3 extract_stable_structs.py \
--json ./VASP_JOBS/prescreening_stability.json \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures

Troubleshooting

All structures filtered out:

  • Threshold may be too strict (try --hull-threshold 0.2)
  • Check if MP API key is working
  • Verify MatterSim is installed correctly

Pre-screening taking too long:

  • Use GPU: --device cuda
  • MP cache should build once per chemical system
  • Check MP API rate limits (built-in backoff)

SLURM Job Management Reference

Basic SLURM Commands

ActionCommand
Submit workflow managerbash run_workflow.sh --max-concurrent 20
Check job queuesqueue -u $USER
Check specific jobsqueue -j <JOBID>
View job logtail -f workflow_manager_<JOBID>.out
Cancel jobscancel <JOBID>
Job historysacct -u $USER
Job detailsscontrol show job <JOBID>

Typical Usage Pattern

# Day 1: Start workflow
ssh your_cluster
cd /scratch/$USER/vaspflow
bash run_workflow.sh --max-concurrent 20
# Note the job ID, then log out# Day 2: Check progress (from anywhere)
ssh your_cluster
cd /scratch/$USER/vaspflow
# Check if manager is still running
squeue -u $USER| grep vaspflow_manager
# Check workflow progress
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
# View manager log
tail -f workflow_manager_*.out

Files

FilePurpose
prescreen.pyMatterSim pre-screening with batch processing
run_prescreen.shSubmit single-GPU pre-screening wrapper
submit_prescreen.shSLURM script for single-GPU pre-screening
submit_parallel_prescreen.shNEW: Parallel multi-GPU prescreening across nodes
merge_prescreen_batches.pyNEW: Merge parallel batch results into single file
plot_e_above_hull.pyVisualize pre-screening energy distribution
extract_stable_structs.pyExtract CIF files for stable structures
workflow_manager.pyVASP workflow with PyXtal symmetrization
run_workflow.shSubmit workflow wrapper (user-facing)
submit_workflow_manager.shSLURM script for workflow manager
workflow_status.pyStatus checking and reporting
reset_failed_jobs.pyReset failed jobs to retry (RELAX/SC/PARCHG)
compute_dft_e_hull.pyCompute DFT energy_above_hull + MatterSim comparison
run_dft_e_hull.shSubmit DFT hull wrapper (user-facing)
submit_dft_e_hull.shSLURM script for DFT hull calculation
compare_energy_methods.pyCompare MatterSim vs DFT energies (uses dft_stability_results.json)
run_compare_energy_method.shSubmit energy method comparison wrapper
submit_compare_energy_method.shSLURM script for energy method comparison
analyze.pyOrchestrates electride analysis (calls Electride.py)
analyze.shSLURM script for analysis job
Electride.pyBader analysis on ELFCAR + PARCHG files
submit_analysis.shSubmit analysis wrapper (user-facing)
filter_comb_db.pyNEW: Filter candidates with stricter volume criteria + PyXtal symmetry
extract_electride_struct.pyExtract CIF files from filtered database
generate_parchg_incars.pyHelper script to generate PARCHG INCARs from vasprun.xml-SC

Key Features:

  • Unified SPE workflow: SC-PARCHG-ELF run sequentially in one SLURM job (2 jobs per structure vs 8)
  • Simplified directory structure: Relax/ and SPE/ subdirectories (vs 7+ subdirectories)
  • Stage markers: SC_DONE, PARCHG_DONE, ELF_DONE, VASP_DONE track progress within SPE job
  • Reduced SLURM overhead: 75% fewer jobs submitted to queue
  • Clean code separation: Python for VASP inputs, bash for workflow orchestration
  • Helper script for PARCHG: Standalone script generates PARCHG INCARs (band indices from vasprun.xml-SC)
  • ISYM=0: VASP internal symmetrization disabled (PyXtal already applied during relaxation)
  • Batch processing: prescreen.py reuses MatterSimCalculator across structures (3-5× faster)
  • Parallel prescreening: submit_parallel_prescreen.sh splits across GPU nodes (linear speedup)
  • Complete GGA coverage: Uses legacy pymatgen.ext.matproj.MPRester for comprehensive GGA/GGA+U phases
  • Strict functional filtering: Only accepts entries with -GGA or -GGA+U suffix (excludes r2SCAN/SCAN)
  • Uncorrected energies: Uses raw DFT energies (no MP corrections) for accurate hull calculations
  • Optional pure-pbe: --pure-pbe flag to filter MP entries to pure GGA-PBE only (exclude PBE+U)
  • Single cache files: mp_mattersim.json and mp_vaspdft.json in VASP_JOBS/ directory
  • PyXtal symmetrization: Automatic structure symmetrization in both prescreening and VASP workflow
  • Two-step electride filtering: Initial analysis saves all data, stricter filtering for high-quality candidates
  • Fast symmetry analysis: PyXtal-based filtering (14× faster than AFLOW)
  • Query-able database: ase db commands for filtering candidates by stability, symmetry, or volumes
  • PDEntry for hulls: Uses PDEntry instead of ComputedEntry for accurate phase diagram analysis
  • reset_failed_jobs.py resets failed VASP jobs to retry them without data loss
  • Integrated hull validation: compute_dft_e_hull.py automatically validates pre-screening accuracy with plots and statistics
  • Energy method comparison: compare_energy_methods.py uses dft_stability_results.json as single source of truth for exact consistency
  • User-friendly wrapper scripts provide consistent interface across all stages

Best Practices

  1. Run pre-screening first with prescreen.py to save 40-60% of VASP computation
  2. Use parallel prescreening (submit_parallel_prescreen.sh) for large datasets (>500 compositions)
  3. Merge batch results with merge_prescreen_batches.py after all parallel jobs complete
  4. Optimize batch size based on GPU memory: 32 for A40/A100 (48GB), 16 for smaller GPUs
  5. Wait for pre-screening to complete before starting VASP workflow
  6. Check pre-screening results (prescreening_stability.json) to verify threshold is appropriate
  7. Inspect cache files (mp_mattersim.json, mp_vaspdft.json) to verify MP data quality
  8. Submit both jobs as SLURM jobs (required on most HPC systems)
  9. Monitor from login node using workflow_status.py instead of viewing logs constantly
  10. Set reasonable max_concurrent (10-20) to avoid queue congestion
  11. Monitor your quota on /scratch periodically (cache files are now much smaller: ~1-5 MB total)
  12. Check failed jobs early to catch systematic issues
  13. Start small (test with 2-3 structures first using --max-compositions 2 --max-structures 2)
  14. Trust PyXtal symmetrization - structures are automatically symmetrized for consistency

Common Workflows

Production Run (Full Scale)

# Step 1: Pre-screening# Option A: Single GPU (for small-medium datasets)
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--device cuda \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0
# Option B: Parallel multi-GPU (recommended for large datasets >500 compositions)
bash submit_parallel_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--batch-size 32 \
--hull-threshold 0.05 \
--max-structures 0 \
--compositions-per-job 400
# After all parallel jobs complete, merge results (JSON + database)
python3 merge_prescreen_batches.py --output-dir ./VASP_JOBS
# Auto-splits compositions across multiple GPU nodes# Each batch processes a different subset (batch 0: comps 0-399, batch 1: 400-799, etc.)# Monitor with: squeue -u $USER | grep prescreen# Wait for completion, check and visualize results
cat VASP_JOBS/prescreening_stability.json | jq '.summary'
cat VASP_JOBS/mp_mattersim.json | jq 'group_by(.chemsys) | map({chemsys: .[0].chemsys, count: length})'
jq '.results[] | select(.passed_prescreening == true) | {structure_id, energy_above_hull}' VASP_JOBS/prescreening_stability.json
python3 plot_e_above_hull.py --bins 100
# (Optional) Extract stable structures for inspection
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# Step 2: VASP workflow (structures automatically symmetrized with PyXtal)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 10 \
--max-structures 0 \
--check-interval 120
# Step 3: Analyze electride candidates
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# Step 4: Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv \
--min-energy 20 \
--min-band 20
# Step 5: Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# Step 6: Query and explore
ase db electride_candidates.db
ase db electride_candidates.db 'e_above_hull<0.05' -s space_group_number-

Resume After Interruption

# Check if still running
squeue -u $USER| grep vaspflow_manager
# If stopped, restart - database persists
bash run_workflow.sh --max-concurrent 20

Integration with MatterGen

# 1. Generate structures with MatterGencd~/mattergen_test/ternary_electride
bash generate_ternary_csp.sh
# 2. Transfer to HPC scratchcd /scratch/$USER
cp -r ~/mattergen_test/results/ternary_csp_electrides mattergen_results/
# 3. Run pre-screening (as SLURM job)cd /scratch/$USER/vaspflow
bash run_prescreen.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-structures 0
# Wait for pre-screening to complete
squeue -u $USER| grep prescreen
cat ./VASP_JOBS/prescreening_stability.json | jq '.summary'# 3b. Visualize and extract stable structures (optional)
python3 plot_e_above_hull.py --input ./VASP_JOBS/prescreening_stability.json
python3 extract_stable_structs.py \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./stable_structures
# 4. Start VASP workflow (as SLURM job)
bash run_workflow.sh \
--results-dir ./mattergen_results/ternary_csp_electrides \
--output-dir ./VASP_JOBS \
--max-concurrent 20
# 5. Monitor and analyze
python workflow_status.py ./VASP_JOBS/workflow.json --compositions
bash submit_analysis.sh --vasp-jobs ./VASP_JOBS
# 6. Filter high-quality candidates
python3 filter_comb_db.py \
--input electride_data.db \
--csv electride_analysis.csv
# 7. Extract CIF files
python3 extract_electride_struct.py \
--db electride_candidates.db \
--output-dir electride_CIF
# 8. Query candidates
ase db electride_candidates.db 'e_above_hull<0.05'

Credits & References

Credits:

Tools & Libraries:

Key Paper:

@article{zhuComputationalDiscoveryInorganic2019,
title = {Computational {{Discovery}} of {{Inorganic Electrides}} from an {{Automated Screening}}},
author = {Zhu, Qiang and Frolov, Timofey and Choudhary, Kamal},
year = 2019,
month = nov,
journal = {Matter},
volume = {1},
number = {5},
pages = {1293--1303},
issn = {2590-2385},
doi = {10.1016/j.matt.2019.06.017},
}
@misc{tao2026acceleratedinorganicelectridesdiscovery,
title={Accelerated Inorganic Electrides Discovery by Generative Models and Hierarchical Screening}, author={Shuo Tao and Qiang Zhu},
year={2026},
eprint={2601.21077},
archivePrefix={arXiv},
primaryClass={cond-mat.mtrl-sci},
url={https://arxiv.org/abs/2601.21077}, }

About

DFT-HT Workflow for screening inorganic electrides

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages