531 lines
13 KiB
Markdown
531 lines
13 KiB
Markdown
# Pymatgen Analysis Modules Reference
|
|
|
|
This reference documents pymatgen's extensive analysis capabilities for materials characterization, property prediction, and computational analysis.
|
|
|
|
## Phase Diagrams and Thermodynamics
|
|
|
|
### Phase Diagram Construction
|
|
|
|
```python
|
|
from pymatgen.analysis.phase_diagram import PhaseDiagram, PDPlotter
|
|
from pymatgen.entries.computed_entries import ComputedEntry
|
|
|
|
# Create entries (composition and energy per atom)
|
|
entries = [
|
|
ComputedEntry("Fe", -8.4),
|
|
ComputedEntry("O2", -4.9),
|
|
ComputedEntry("FeO", -6.7),
|
|
ComputedEntry("Fe2O3", -8.3),
|
|
ComputedEntry("Fe3O4", -9.1),
|
|
]
|
|
|
|
# Build phase diagram
|
|
pd = PhaseDiagram(entries)
|
|
|
|
# Get stable entries
|
|
stable_entries = pd.stable_entries
|
|
|
|
# Get energy above hull (stability)
|
|
entry_to_test = ComputedEntry("Fe2O3", -8.0)
|
|
energy_above_hull = pd.get_e_above_hull(entry_to_test)
|
|
|
|
# Get decomposition products
|
|
decomp = pd.get_decomposition(entry_to_test.composition)
|
|
# Returns: {entry1: fraction1, entry2: fraction2, ...}
|
|
|
|
# Get equilibrium reaction energy
|
|
rxn_energy = pd.get_equilibrium_reaction_energy(entry_to_test)
|
|
|
|
# Plot phase diagram
|
|
plotter = PDPlotter(pd)
|
|
plotter.show()
|
|
plotter.write_image("phase_diagram.png")
|
|
```
|
|
|
|
### Chemical Potential Diagrams
|
|
|
|
```python
|
|
from pymatgen.analysis.phase_diagram import ChemicalPotentialDiagram
|
|
|
|
# Create chemical potential diagram
|
|
cpd = ChemicalPotentialDiagram(entries, limits={"O": (-10, 0)})
|
|
|
|
# Get domains (stability regions)
|
|
domains = cpd.domains
|
|
```
|
|
|
|
### Pourbaix Diagrams
|
|
|
|
Electrochemical phase diagrams with pH and potential axes.
|
|
|
|
```python
|
|
from pymatgen.analysis.pourbaix_diagram import PourbaixDiagram, PourbaixPlotter
|
|
from pymatgen.entries.computed_entries import ComputedEntry
|
|
|
|
# Create entries with corrections for aqueous species
|
|
entries = [...] # Include solids and ions
|
|
|
|
# Build Pourbaix diagram
|
|
pb = PourbaixDiagram(entries)
|
|
|
|
# Get stable entry at specific pH and potential
|
|
stable_entry = pb.get_stable_entry(pH=7, V=0)
|
|
|
|
# Plot
|
|
plotter = PourbaixPlotter(pb)
|
|
plotter.show()
|
|
```
|
|
|
|
## Structure Analysis
|
|
|
|
### Structure Matching and Comparison
|
|
|
|
```python
|
|
from pymatgen.analysis.structure_matcher import StructureMatcher
|
|
|
|
matcher = StructureMatcher()
|
|
|
|
# Check if structures match
|
|
is_match = matcher.fit(struct1, struct2)
|
|
|
|
# Get mapping between structures
|
|
mapping = matcher.get_mapping(struct1, struct2)
|
|
|
|
# Group similar structures
|
|
grouped = matcher.group_structures([struct1, struct2, struct3, ...])
|
|
```
|
|
|
|
### Ewald Summation
|
|
|
|
Calculate electrostatic energy of ionic structures.
|
|
|
|
```python
|
|
from pymatgen.analysis.ewald import EwaldSummation
|
|
|
|
ewald = EwaldSummation(struct)
|
|
total_energy = ewald.total_energy # In eV
|
|
forces = ewald.forces # Forces on each site
|
|
```
|
|
|
|
### Symmetry Analysis
|
|
|
|
```python
|
|
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
|
|
|
|
sga = SpacegroupAnalyzer(struct)
|
|
|
|
# Get space group information
|
|
spacegroup_symbol = sga.get_space_group_symbol() # e.g., "Fm-3m"
|
|
spacegroup_number = sga.get_space_group_number() # e.g., 225
|
|
crystal_system = sga.get_crystal_system() # e.g., "cubic"
|
|
|
|
# Get symmetrized structure
|
|
sym_struct = sga.get_symmetrized_structure()
|
|
equivalent_sites = sym_struct.equivalent_sites
|
|
|
|
# Get conventional/primitive cells
|
|
conventional = sga.get_conventional_standard_structure()
|
|
primitive = sga.get_primitive_standard_structure()
|
|
|
|
# Get symmetry operations
|
|
symmetry_ops = sga.get_symmetry_operations()
|
|
```
|
|
|
|
## Local Environment Analysis
|
|
|
|
### Coordination Environment
|
|
|
|
```python
|
|
from pymatgen.analysis.local_env import (
|
|
VoronoiNN, # Voronoi tessellation
|
|
CrystalNN, # Crystal-based
|
|
MinimumDistanceNN, # Distance cutoff
|
|
BrunnerNN_real, # Brunner method
|
|
)
|
|
|
|
# Voronoi nearest neighbors
|
|
voronoi = VoronoiNN()
|
|
neighbors = voronoi.get_nn_info(struct, n=0) # Neighbors of site 0
|
|
|
|
# CrystalNN (recommended for most cases)
|
|
crystalnn = CrystalNN()
|
|
neighbors = crystalnn.get_nn_info(struct, n=0)
|
|
|
|
# Analyze all sites
|
|
for i, site in enumerate(struct):
|
|
neighbors = voronoi.get_nn_info(struct, i)
|
|
coordination_number = len(neighbors)
|
|
print(f"Site {i} ({site.species_string}): CN = {coordination_number}")
|
|
```
|
|
|
|
### Coordination Geometry (ChemEnv)
|
|
|
|
Detailed coordination environment identification.
|
|
|
|
```python
|
|
from pymatgen.analysis.chemenv.coordination_environments.coordination_geometry_finder import LocalGeometryFinder
|
|
from pymatgen.analysis.chemenv.coordination_environments.chemenv_strategies import SimplestChemenvStrategy
|
|
|
|
lgf = LocalGeometryFinder()
|
|
lgf.setup_structure(struct)
|
|
|
|
# Get coordination environment for site
|
|
se = lgf.compute_structure_environments(only_indices=[0])
|
|
strategy = SimplestChemenvStrategy()
|
|
lse = strategy.get_site_coordination_environment(se[0])
|
|
|
|
print(f"Coordination: {lse}")
|
|
```
|
|
|
|
### Bond Valence Sum
|
|
|
|
```python
|
|
from pymatgen.analysis.bond_valence import BVAnalyzer
|
|
|
|
bva = BVAnalyzer()
|
|
|
|
# Calculate oxidation states
|
|
valences = bva.get_valences(struct)
|
|
|
|
# Get structure with oxidation states
|
|
struct_with_oxi = bva.get_oxi_state_decorated_structure(struct)
|
|
```
|
|
|
|
## Surface and Interface Analysis
|
|
|
|
### Surface (Slab) Generation
|
|
|
|
```python
|
|
from pymatgen.core.surface import SlabGenerator, generate_all_slabs
|
|
|
|
# Generate slabs for a specific Miller index
|
|
slabgen = SlabGenerator(
|
|
struct,
|
|
miller_index=(1, 1, 1),
|
|
min_slab_size=10.0, # Minimum slab thickness (Å)
|
|
min_vacuum_size=10.0, # Minimum vacuum thickness (Å)
|
|
center_slab=True
|
|
)
|
|
|
|
slabs = slabgen.get_slabs()
|
|
|
|
# Generate all slabs up to a Miller index
|
|
all_slabs = generate_all_slabs(
|
|
struct,
|
|
max_index=2,
|
|
min_slab_size=10.0,
|
|
min_vacuum_size=10.0
|
|
)
|
|
```
|
|
|
|
### Wulff Shape Construction
|
|
|
|
```python
|
|
from pymatgen.analysis.wulff import WulffShape
|
|
|
|
# Define surface energies (J/m²)
|
|
surface_energies = {
|
|
(1, 0, 0): 1.0,
|
|
(1, 1, 0): 1.1,
|
|
(1, 1, 1): 0.9,
|
|
}
|
|
|
|
wulff = WulffShape(struct.lattice, surface_energies, symm_reduce=True)
|
|
|
|
# Get effective radius and surface area
|
|
effective_radius = wulff.effective_radius
|
|
surface_area = wulff.surface_area
|
|
volume = wulff.volume
|
|
|
|
# Visualize
|
|
wulff.show()
|
|
```
|
|
|
|
### Adsorption Site Finding
|
|
|
|
```python
|
|
from pymatgen.analysis.adsorption import AdsorbateSiteFinder
|
|
|
|
asf = AdsorbateSiteFinder(slab)
|
|
|
|
# Find adsorption sites
|
|
ads_sites = asf.find_adsorption_sites()
|
|
# Returns dictionary: {"ontop": [...], "bridge": [...], "hollow": [...]}
|
|
|
|
# Generate structures with adsorbates
|
|
from pymatgen.core import Molecule
|
|
adsorbate = Molecule("O", [[0, 0, 0]])
|
|
|
|
ads_structs = asf.generate_adsorption_structures(
|
|
adsorbate,
|
|
repeat=[2, 2, 1], # Supercell to reduce adsorbate coverage
|
|
)
|
|
```
|
|
|
|
### Interface Construction
|
|
|
|
```python
|
|
from pymatgen.analysis.interfaces.coherent_interfaces import CoherentInterfaceBuilder
|
|
|
|
# Build interface between two materials
|
|
builder = CoherentInterfaceBuilder(
|
|
substrate_structure=substrate,
|
|
film_structure=film,
|
|
substrate_miller=(0, 0, 1),
|
|
film_miller=(1, 1, 1),
|
|
)
|
|
|
|
interfaces = builder.get_interfaces()
|
|
```
|
|
|
|
## Magnetism
|
|
|
|
### Magnetic Structure Analysis
|
|
|
|
```python
|
|
from pymatgen.analysis.magnetism import CollinearMagneticStructureAnalyzer
|
|
|
|
analyzer = CollinearMagneticStructureAnalyzer(struct)
|
|
|
|
# Get magnetic ordering
|
|
ordering = analyzer.ordering # e.g., "FM" (ferromagnetic), "AFM", "FiM"
|
|
|
|
# Get magnetic space group
|
|
mag_space_group = analyzer.get_structure_with_spin().get_space_group_info()
|
|
```
|
|
|
|
### Magnetic Ordering Enumeration
|
|
|
|
```python
|
|
from pymatgen.transformations.advanced_transformations import MagOrderingTransformation
|
|
|
|
# Enumerate possible magnetic orderings
|
|
mag_trans = MagOrderingTransformation({"Fe": 5.0}) # Magnetic moment in μB
|
|
transformed_structures = mag_trans.apply_transformation(struct, return_ranked_list=True)
|
|
```
|
|
|
|
## Electronic Structure Analysis
|
|
|
|
### Band Structure Analysis
|
|
|
|
```python
|
|
from pymatgen.electronic_structure.bandstructure import BandStructureSymmLine
|
|
from pymatgen.electronic_structure.plotter import BSPlotter
|
|
|
|
# Read band structure from VASP calculation
|
|
from pymatgen.io.vasp import Vasprun
|
|
vasprun = Vasprun("vasprun.xml")
|
|
bs = vasprun.get_band_structure()
|
|
|
|
# Get band gap
|
|
band_gap = bs.get_band_gap()
|
|
# Returns: {'energy': gap_value, 'direct': True/False, 'transition': '...'}
|
|
|
|
# Check if metal
|
|
is_metal = bs.is_metal()
|
|
|
|
# Get VBM and CBM
|
|
vbm = bs.get_vbm()
|
|
cbm = bs.get_cbm()
|
|
|
|
# Plot band structure
|
|
plotter = BSPlotter(bs)
|
|
plotter.show()
|
|
plotter.save_plot("band_structure.png")
|
|
```
|
|
|
|
### Density of States (DOS)
|
|
|
|
```python
|
|
from pymatgen.electronic_structure.dos import CompleteDos
|
|
from pymatgen.electronic_structure.plotter import DosPlotter
|
|
|
|
# Read DOS from VASP calculation
|
|
vasprun = Vasprun("vasprun.xml")
|
|
dos = vasprun.complete_dos
|
|
|
|
# Get total DOS
|
|
total_dos = dos.densities
|
|
|
|
# Get projected DOS
|
|
pdos = dos.get_element_dos() # By element
|
|
site_dos = dos.get_site_dos(struct[0]) # For specific site
|
|
spd_dos = dos.get_spd_dos() # By orbital (s, p, d)
|
|
|
|
# Plot DOS
|
|
plotter = DosPlotter()
|
|
plotter.add_dos("Total", dos)
|
|
plotter.show()
|
|
```
|
|
|
|
### Fermi Surface
|
|
|
|
```python
|
|
from pymatgen.electronic_structure.boltztrap2 import BoltztrapRunner
|
|
|
|
runner = BoltztrapRunner(struct, nelec=n_electrons)
|
|
runner.run()
|
|
|
|
# Get transport properties at different temperatures
|
|
results = runner.get_results()
|
|
```
|
|
|
|
## Diffraction
|
|
|
|
### X-ray Diffraction (XRD)
|
|
|
|
```python
|
|
from pymatgen.analysis.diffraction.xrd import XRDCalculator
|
|
|
|
xrd = XRDCalculator()
|
|
|
|
pattern = xrd.get_pattern(struct, two_theta_range=(0, 90))
|
|
|
|
# Get peak data
|
|
for peak in pattern.hkls:
|
|
print(f"2θ = {peak['2theta']:.2f}°, hkl = {peak['hkl']}, I = {peak['intensity']:.1f}")
|
|
|
|
# Plot pattern
|
|
pattern.plot()
|
|
```
|
|
|
|
### Neutron Diffraction
|
|
|
|
```python
|
|
from pymatgen.analysis.diffraction.neutron import NDCalculator
|
|
|
|
nd = NDCalculator()
|
|
pattern = nd.get_pattern(struct)
|
|
```
|
|
|
|
## Elasticity and Mechanical Properties
|
|
|
|
```python
|
|
from pymatgen.analysis.elasticity import ElasticTensor, Stress, Strain
|
|
|
|
# Create elastic tensor from matrix
|
|
elastic_tensor = ElasticTensor([[...]]) # 6x6 or 3x3x3x3 matrix
|
|
|
|
# Get mechanical properties
|
|
bulk_modulus = elastic_tensor.k_voigt # Voigt bulk modulus (GPa)
|
|
shear_modulus = elastic_tensor.g_voigt # Shear modulus (GPa)
|
|
youngs_modulus = elastic_tensor.y_mod # Young's modulus (GPa)
|
|
|
|
# Apply strain
|
|
strain = Strain([[0.01, 0, 0], [0, 0, 0], [0, 0, 0]])
|
|
stress = elastic_tensor.calculate_stress(strain)
|
|
```
|
|
|
|
## Reaction Analysis
|
|
|
|
### Reaction Computation
|
|
|
|
```python
|
|
from pymatgen.analysis.reaction_calculator import ComputedReaction
|
|
|
|
reactants = [ComputedEntry("Fe", -8.4), ComputedEntry("O2", -4.9)]
|
|
products = [ComputedEntry("Fe2O3", -8.3)]
|
|
|
|
rxn = ComputedReaction(reactants, products)
|
|
|
|
# Get balanced equation
|
|
balanced_rxn = rxn.normalized_repr # e.g., "2 Fe + 1.5 O2 -> Fe2O3"
|
|
|
|
# Get reaction energy
|
|
energy = rxn.calculated_reaction_energy # eV per formula unit
|
|
```
|
|
|
|
### Reaction Path Finding
|
|
|
|
```python
|
|
from pymatgen.analysis.path_finder import ChgcarPotential, NEBPathfinder
|
|
|
|
# Read charge density
|
|
chgcar_potential = ChgcarPotential.from_file("CHGCAR")
|
|
|
|
# Find diffusion path
|
|
neb_path = NEBPathfinder(
|
|
start_struct,
|
|
end_struct,
|
|
relax_sites=[i for i in range(len(start_struct))],
|
|
v=chgcar_potential
|
|
)
|
|
|
|
images = neb_path.images # Interpolated structures for NEB
|
|
```
|
|
|
|
## Molecular Analysis
|
|
|
|
### Bond Analysis
|
|
|
|
```python
|
|
# Get covalent bonds
|
|
bonds = mol.get_covalent_bonds()
|
|
|
|
for bond in bonds:
|
|
print(f"{bond.site1.species_string} - {bond.site2.species_string}: {bond.length:.2f} Å")
|
|
```
|
|
|
|
### Molecule Graph
|
|
|
|
```python
|
|
from pymatgen.analysis.graphs import MoleculeGraph
|
|
from pymatgen.analysis.local_env import OpenBabelNN
|
|
|
|
# Build molecule graph
|
|
mg = MoleculeGraph.with_local_env_strategy(mol, OpenBabelNN())
|
|
|
|
# Get fragments
|
|
fragments = mg.get_disconnected_fragments()
|
|
|
|
# Find rings
|
|
rings = mg.find_rings()
|
|
```
|
|
|
|
## Spectroscopy
|
|
|
|
### X-ray Absorption Spectroscopy (XAS)
|
|
|
|
```python
|
|
from pymatgen.analysis.xas.spectrum import XAS
|
|
|
|
# Read XAS spectrum
|
|
xas = XAS.from_file("xas.dat")
|
|
|
|
# Normalize and process
|
|
xas.normalize()
|
|
```
|
|
|
|
## Additional Analysis Tools
|
|
|
|
### Grain Boundaries
|
|
|
|
```python
|
|
from pymatgen.analysis.gb.grain import GrainBoundaryGenerator
|
|
|
|
gb_gen = GrainBoundaryGenerator(struct)
|
|
gb_structures = gb_gen.generate_grain_boundaries(
|
|
rotation_axis=[0, 0, 1],
|
|
rotation_angle=36.87, # degrees
|
|
)
|
|
```
|
|
|
|
### Prototypes and Structure Matching
|
|
|
|
```python
|
|
from pymatgen.analysis.prototypes import AflowPrototypeMatcher
|
|
|
|
matcher = AflowPrototypeMatcher()
|
|
prototype = matcher.get_prototypes(struct)
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
1. **Start simple**: Use basic analysis before advanced methods
|
|
2. **Validate results**: Cross-check analysis with multiple methods
|
|
3. **Consider symmetry**: Use `SpacegroupAnalyzer` to reduce computational cost
|
|
4. **Check convergence**: Ensure input structures are well-converged
|
|
5. **Use appropriate methods**: Different analyses have different accuracy/speed tradeoffs
|
|
6. **Visualize results**: Use built-in plotters for quick validation
|
|
7. **Save intermediate results**: Complex analyses can be time-consuming
|