Exsolution Simulation¶
This tutorial covers simulating exsolution processes in perovskite materials, where transition metal cations migrate from the bulk to the surface under reducing conditions to form metallic nanoparticles.
Background¶
Exsolution is a phenomenon where B-site transition metals (Ni, Co, Fe) in perovskite oxides (e.g., La₀.₄Sr₀.₄Ti₀.₉Ni₀.₁O₃) emerge from the lattice to form metallic nanoparticles on the surface. Key features:
- Occurs under reducing atmospheres (H₂, NH₃)
- Creates socketed nanoparticles anchored into the surface
- Generates oxygen vacancies that enhance catalytic activity
- Produces highly stable, sinter-resistant metal particles
Exsolution Pathway¶
The exsolution process involves four stages:
1. Pristine → 2. Defective → 3. Segregated → 4. Exsolved
Perovskite + Vacancies + Surface B + Nanoparticle
Quick Start¶
Create Exsolution Structures¶
from nh3sofc.structure import BulkStructure, SurfaceBuilder, ExsolutionBuilder
from nh3sofc import write_poscar
# Load perovskite structure
bulk = BulkStructure.from_cif("LaSrTiNiO3.cif")
# Create (001) surface
surface = SurfaceBuilder(bulk).create_surface(
miller_index=(0, 0, 1),
layers=6,
vacuum=15.0
)
surface.fix_bottom_layers(2)
# Create exsolution builder
builder = ExsolutionBuilder(surface)
# Generate full exsolution pathway
pathway = builder.create_exsolution_pathway(
metal="Ni",
particle_size=13,
vacancy_fraction=0.1
)
# Save structures with proper POSCAR format (atoms sorted automatically)
work_dir = "work/exsolution/Ni13"
for step in pathway:
atoms = step["atoms"]
stage = step["stage"]
write_poscar(atoms, f"{work_dir}/{stage}.vasp")
print(f"{stage}: {step['description']}")
Individual Steps¶
1. Identify Perovskite Sites¶
sites = builder.identify_perovskite_sites()
print(f"A-site atoms: {len(sites['A_site'])}") # La, Sr
print(f"B-site atoms: {len(sites['B_site'])}") # Ti, Ni
print(f"O-site atoms: {len(sites['O_site'])}") # O
2. Create Defective Perovskite¶
from nh3sofc import write_poscar
defective = builder.create_defective_perovskite(
a_site_vacancy_fraction=0.05, # 5% A-site vacancies
b_site_vacancy_fraction=0.1, # 10% B-site (Ni) vacancies
oxygen_vacancy_fraction=0.08, # 8% O vacancies
b_site_element="Ni", # Specifically remove Ni
random_seed=42
)
write_poscar(defective, "work/exsolution/defective.vasp")
3. Create Nanoparticle on Surface¶
exsolved = builder.create_nanoparticle(
metal="Ni",
n_atoms=13, # Ni13 cluster (magic number)
shape="hemispherical", # or "icosahedral"
position="hollow", # or "ontop", "bridge", "random"
interface_distance=2.0, # Metal-oxide distance
socketed=True, # Remove surface atoms (real exsolution)
random_seed=42
)
write_poscar(exsolved, "work/exsolution/exsolved_Ni13.vasp")
Running Calculations¶
Single Exsolution Study¶
from nh3sofc.workflows import ExsolutionWorkflow
wf = ExsolutionWorkflow(
atoms=surface.atoms,
work_dir="./exsolution_Ni13",
metal="Ni",
particle_size=13,
vacancy_fraction=0.1,
calculator="vasp",
encut=520,
hubbard_u={"Ni": 6.2, "Ti": 3.0},
vdw="D3BJ",
)
# Generate all structures
wf.generate_pathway_structures()
# Setup VASP calculations
wf.setup()
# Submit jobs
# cd exsolution_Ni13 && bash submit_all.sh
Parse Results¶
# After VASP calculations complete
results = wf.parse_results()
print(f"Pristine energy: {results['pristine']['energy']:.2f} eV")
print(f"Exsolved energy: {results['exsolved']['energy']:.2f} eV")
print(f"Exsolution energy: {results['exsolution_energy']:.2f} eV")
print(f"Favorable: {results['summary']['favorable']}")
Energetics Analysis¶
Calculate Exsolution Driving Force¶
from nh3sofc.analysis import ExsolutionEnergetics
energetics = ExsolutionEnergetics(
metal="Ni",
temperature=873.0, # 600°C
p_o2=1e-20 # Reducing atmosphere
)
# Set reference
energetics.set_reference_energies(e_pristine=-250.0)
# Add DFT results
energetics.add_stage("pristine", -250.0)
energetics.add_stage("defective", -235.0, n_o_vacancies=4)
energetics.add_stage("segregated", -238.0)
energetics.add_stage("exsolved", -265.0, n_particle_atoms=13, n_o_vacancies=4)
# Calculate thermodynamics
result = energetics.get_exsolution_driving_force()
print(f"ΔG_exsolution = {result['delta_G']:.2f} eV")
print(f"μ_O = {result['mu_O']:.2f} eV")
print(f"Favorable: {result['favorable']}")
# Print summary
energetics.print_summary()
Effect of Temperature and Pressure¶
import numpy as np
# Vary temperature
for T in [673, 773, 873, 973]:
result = energetics.get_exsolution_driving_force(temperature=T)
print(f"T={T}K: ΔG={result['delta_G']:.2f} eV")
# Vary oxygen partial pressure
for log_p in [-25, -20, -15, -10]:
result = energetics.get_exsolution_driving_force(p_o2=10**log_p)
print(f"log(p_O2)={log_p}: ΔG={result['delta_G']:.2f} eV")
High-Throughput Screening¶
Screen Multiple Metals and Sizes¶
from nh3sofc.workflows import ExsolutionScreeningWorkflow
screening = ExsolutionScreeningWorkflow(
base_structure=surface.atoms,
parameter_space={
"metal": ["Ni", "Co", "Fe"],
"particle_size": [1, 4, 13],
"vacancy_fraction": [0.05, 0.1, 0.15],
},
work_dir="./exsolution_screening",
calculator="vasp",
encut=520,
)
# Generate all combinations
configs = screening.generate_all()
print(f"Total configurations: {len(configs)}")
# Setup calculations
screening.setup_all()
# After completion:
results = screening.parse_all()
best = screening.get_best_result(metric="exsolution_energy", minimize=True)
print(f"Best configuration: {best['config']}")
NH3 Catalysis on Exsolved Particles¶
Identify Adsorption Sites¶
Exsolved particles have multiple unique adsorption site types:
# Get adsorption sites on exsolved structure
sites = builder.get_adsorption_sites(exsolved)
print(f"Metal top sites: {len(sites['metal_top'])}")
print(f"Interface edge sites: {len(sites['interface_edge'])}")
print(f"Vacancy sites: {len(sites['vacancy_site'])}")
print(f"Oxide surface sites: {len(sites['oxide_surface'])}")
Couple with NH3 Decomposition¶
# Continue from exsolution workflow
decomp_wf = wf.couple_with_decomposition()
decomp_wf.setup()
# This creates NH3 decomposition pathway on the exsolved particle
Compare with Clean Surface¶
# Energies from NH3 decomposition on exsolved particle
exsolved_energies = {
"NH3*": -0.8,
"NH2*+H*": 0.2,
"NH*+2H*": 0.5,
"N*+3H*": 0.3,
}
# Energies from clean perovskite surface
clean_energies = {
"NH3*": -0.5,
"NH2*+H*": 0.6,
"NH*+2H*": 1.2,
"N*+3H*": 0.9,
}
comparison = energetics.compare_with_clean_surface(
exsolved_energies,
clean_energies
)
print("More favorable on exsolved:", comparison["more_favorable_on_exsolved"])
print("More favorable on clean:", comparison["more_favorable_on_clean"])
Key Differences: Exsolved vs. Deposited Catalysts¶
| Feature | Exsolved | Deposited |
|---|---|---|
| Anchoring | Socketed into support | Weakly bound |
| Sintering | Resistant | Prone to coalescence |
| Active sites | Metal + interface + vacancies | Metal surface only |
| Coking | Resistant (small particles) | Variable |
Best Practices¶
- Particle sizes: Use magic numbers (1, 4, 7, 13, 19) for stable clusters
- Vacancy coupling: ~2 O vacancies per reduced B-site cation
- Socket modeling: Enable
socketed=Truefor realistic exsolution - Temperature: Typical exsolution occurs at 600-900°C
- Atmosphere: Use very low p(O₂) (~10⁻²⁰ atm) for reducing conditions
Example Directory Structure¶
exsolution_study/
├── pristine/
│ ├── INCAR, POSCAR, KPOINTS, POTCAR
│ └── run.pbs
├── defective/
│ └── ...
├── segregated/
│ └── ...
├── exsolved/
│ └── ...
├── submit_all.sh
└── nh3_decomposition/ # From couple_with_decomposition()
├── NH3/
├── NH2_H/
└── ...
Next Steps¶
- Thermochemistry - Calculate Gibbs free energies
- Microkinetics - Model reaction rates on exsolved particles
- Surface Comparison - Compare different catalyst surfaces