Skip to content
Merged

Dev #249

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions other/experiments/mtrsm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## Usage

### With standalone scripts

Install dependencies (using pyenv):

```bash
pyenv local 3.10.13
python -m venv .venv-3.10.13
source .venv-3.10.13/bin/activate
pip install mattersim
```

Run the script(s):

```bash
source .venv-3.10.13/bin/activate
python <script_name.py>
```

### With JupyterLab

Install dependencies:

```bash
pyenv local 3.10.13
python -m venv .venv-3.10.13
source .venv-3.10.13/bin/activate
pip install "mat3ra-api-examples[forcefields]"
```

As below. With `pyenv`.

```bash
pyenv local 3.10.13
python -m venv .venv-3.10.13
source .venv-3.10.13/bin/activate
pip install mattersim
```

See the included notebook.
269 changes: 269 additions & 0 deletions other/experiments/mtrsm/calculate_energy_for_vacancy_mattersim.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "ba05a8b053f7ed1f",
"metadata": {},
"source": [
"# Calculate Vacancy Formation Energy in Silicon using MatterSim Potential\n",
"\n",
"This notebook demonstrates how to compute the vacancy formation energy in silicon using the MatterSim potential within the Mat3ra framework.\n",
"\n",
"## Methodology\n",
"\n",
"The vacancy formation energy is calculated using the following approach:\n",
"\n",
"1. **Create pristine supercell**: Build a silicon supercell from the unit cell and relax it using MatterSim potential\n",
"2. **Create vacancy**: Remove a single atom from the center of the supercell\n",
"3. **Relax vacancy structure**: Optimize the geometry of the defective supercell\n",
"4. **Calculate formation energy**: Compute the energy difference according to the formula:\n",
" \n",
" E_formation = E_vacancy - (N_vacancy/N_bulk) × E_bulk\n",
" \n",
" where:\n",
" - E_vacancy: Total energy of the supercell with vacancy\n",
" - E_bulk: Total energy of the pristine supercell\n",
" - N_vacancy: Number of atoms in vacancy supercell\n",
" - N_bulk: Number of atoms in pristine supercell"
]
},
{
"cell_type": "code",
"id": "39067e0f5d2c0ffb",
"metadata": {},
"source": [
"# Install required packages if not already installed\n",
"# INFO: if not installed correctly, clear environment and run `pip install .[forcefields]` in the terminal\n",
"try:\n",
" import mattersim\n",
"except ImportError:\n",
" import subprocess, sys\n",
" subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \".[forcefields]\", \"--quiet\"], check=False)\n",
" import mattersim"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"id": "ad71b3bcdb13e36a",
"metadata": {},
"source": [
"## 1. Prepare materials\n",
"### 1.1. Load material data"
]
},
{
"cell_type": "code",
"id": "2819d078b48216b9",
"metadata": {},
"source": [
"from mat3ra.standata.materials import Materials\n",
"from mat3ra.made.material import Material\n",
"\n",
"material = Material.create(Materials.get_by_name_first_match(\"Si\"))"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"id": "f011303e40ab0ee5",
"metadata": {},
"source": [
"### 1.2. Add vacancy to material"
]
},
{
"cell_type": "code",
"id": "b7e53d295d59fe89",
"metadata": {},
"source": [
"from mat3ra.made.tools.helpers import create_vacancy, create_supercell\n",
"\n",
"supercell = create_supercell(material, scaling_factor=[2,2,2])\n",
"material_with_vacancy = create_vacancy(supercell, coordinate=[0.5, 0.5, 0.5], placement_method=\"closest_site\")"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"id": "45c3dade8bcd52b3",
"metadata": {},
"source": [
"## 1.3. Visualize materials"
]
},
{
"cell_type": "code",
"id": "4b91a2ae59c983a3",
"metadata": {},
"source": [
"from utils.visualize import visualize_materials\n",
"\n",
"visualize_materials([material, supercell, material_with_vacancy], rotation=\"-90x,-90y\")"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"id": "8ce27a1c8864c29f",
"metadata": {},
"source": [
"## 2. Setup calculation\n",
"### 2.1. Convert to ASE atoms"
]
},
{
"cell_type": "code",
"id": "62b389e5458ce7c2",
"metadata": {},
"source": [
"from mat3ra.made.tools.convert import to_ase\n",
"\n",
"material_atoms = to_ase(material)\n",
"material_with_vacancy_atoms = to_ase(material_with_vacancy)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"id": "c4c3b2a928a369ad",
"metadata": {},
"source": [
"### 2.2. Setup MatterSim calculator"
]
},
{
"cell_type": "code",
"id": "361cd269cb3e2db4",
"metadata": {},
"source": [
"from mattersim.forcefield.potential import MatterSimCalculator\n",
"from mattersim.applications.relax import Relaxer\n",
"\n",
"material_atoms.calc = MatterSimCalculator()\n",
"material_with_vacancy_atoms.calc = MatterSimCalculator()\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"id": "8119275fe9ffb1d8",
"metadata": {},
"source": [
"### 2.3. Relax structures"
]
},
{
"cell_type": "code",
"id": "48cbd2f29d0cbd2c",
"metadata": {},
"source": [
"relaxer = Relaxer(optimizer=\"BFGS\", constrain_symmetry=True)\n",
"relaxer.relax(material_atoms, steps=500) # In-place relaxation\n",
"relaxer.relax(material_with_vacancy_atoms, steps=500) # In-place relaxation\n"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"id": "116af57af6793bb",
"metadata": {},
"source": [
"### 2.4. Visualize relaxed structures"
]
},
{
"cell_type": "code",
"id": "6426cc56c5d51eef",
"metadata": {},
"source": [
"from mat3ra.made.tools.convert import from_ase\n",
"\n",
"relaxed_material = Material.create(from_ase(material_atoms))\n",
"relaxed_material_with_vacancy = Material.create(from_ase(material_with_vacancy_atoms))\n",
"\n",
"visualize_materials([relaxed_material, supercell, relaxed_material_with_vacancy], rotation=\"-90x,-90y\")"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"id": "7754f5d01964b082",
"metadata": {},
"source": [
"## 3. Calculate vacancy formation energy\n",
"\n",
"### 3.1. Get energies and atom counts"
]
},
{
"cell_type": "code",
"id": "2f4694776e7d1430",
"metadata": {},
"source": [
"energy_bulk = material_atoms.get_potential_energy()\n",
"n_atoms_bulk = len(material_atoms)\n",
"energy_vacancy = material_with_vacancy_atoms.get_potential_energy()\n",
"n_atoms_vac = len(material_with_vacancy_atoms)"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"id": "baae670f86c9b639",
"metadata": {},
"source": [
"### 3.2. Calculate vacancy formation energy"
]
},
{
"cell_type": "code",
"id": "430936d099f5b816",
"metadata": {},
"source": [
"e_vacancy = energy_vacancy - (n_atoms_vac / n_atoms_bulk * energy_bulk)\n",
"print(f\"Vacancy formation energy: {e_vacancy:.4f} eV\")\n"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": "",
"id": "fa73a94409748e1c",
"outputs": [],
"execution_count": null
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
16 changes: 16 additions & 0 deletions other/experiments/mtrsm/minimal_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import torch
from loguru import logger
from ase.build import bulk
from ase.units import GPa
from mattersim.forcefield import MatterSimCalculator

device = "cuda" if torch.cuda.is_available() else "cpu"
logger.info(f"Running MatterSim on {device}")

si = bulk("Si", "diamond", a=5.43)
si.calc = MatterSimCalculator(device=device)
logger.info(f"Energy (eV) = {si.get_potential_energy()}")
logger.info(f"Energy per atom (eV/atom) = {si.get_potential_energy()/len(si)}")
logger.info(f"Forces of first atom (eV/A) = {si.get_forces()[0]}")
logger.info(f"Stress[0][0] (eV/A^3) = {si.get_stress(voigt=False)[0][0]}")
logger.info(f"Stress[0][0] (GPa) = {si.get_stress(voigt=False)[0][0] / GPa}")
26 changes: 26 additions & 0 deletions other/experiments/mtrsm/phonon_dispersion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import numpy as np
from ase.build import bulk
from ase.units import GPa
from ase.visualize import view
from mattersim.forcefield.potential import MatterSimCalculator
from mattersim.applications.phonon import PhononWorkflow

# initialize the structure of silicon
si = bulk("Si")

# attach the calculator to the atoms object
si.calc = MatterSimCalculator()

ph = PhononWorkflow(
atoms=si,
find_prim = False,
work_dir = "./tmp/phonon_si_example",
amplitude = 0.01,
supercell_matrix = np.diag([4,4,4]),
)

has_imag, phonons = ph.run()
print(f"Has imaginary phonon: {has_imag}")
print(f"Phonon frequencies: {phonons}")


23 changes: 23 additions & 0 deletions other/experiments/mtrsm/structure_optimization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import numpy as np
from ase.build import bulk
from ase.units import GPa
from mattersim.forcefield.potential import MatterSimCalculator
from mattersim.applications.relax import Relaxer

# initialize the structure of silicon
si = bulk("Si", "diamond", a=5.43)

# perturb the structure
si.positions += 0.1 * np.random.randn(len(si), 3)

# attach the calculator to the atoms object
si.calc = MatterSimCalculator()

# initialize the relaxation object
relaxer = Relaxer(
optimizer="BFGS", # the optimization method
filter="ExpCellFilter", # filter to apply to the cell
constrain_symmetry=True, # whether to constrain the symmetry
)

relaxed_structure = relaxer.relax(si, steps=500)
Loading
Loading