diff --git a/other/experiments/mtrgn/README.md b/other/experiments/mtrgn/README.md new file mode 100644 index 00000000..1e325c23 --- /dev/null +++ b/other/experiments/mtrgn/README.md @@ -0,0 +1,99 @@ +# Example of using Mattergen to generate a material + +## 1. Installation and setup + +### 1.0. Clone the repository + +```bash +git clone https://github.com/Exabyte-io/mattergen.git && cd mattergen +``` + +### 1.1. Create virtual environment + +```bash +pyenv local 3.10.12 +python -m venv .venv-3.10.12 +source .venv-3.10.12/bin/activate +``` + +### 1.2. Install the package + +Try this approach first: + +```bash +pip install -e . +``` + +In case of issues, try using `uv`: + +```bash +pip install uv +uv pip install -e . +``` + +### 1.3. Fix torch compatibility + +In case of compatibility issues with torch and torch-scatter, you can try to reinstall specific versions. + +Below are the directives for Apple Silicon, 12.6 OSX: + +```bash +pip install --no-cache-dir --force-reinstall "torch==2.4.1" +``` + +In case `torch-scatter` installation fails, try: +```bash +pip install --no-cache-dir --force-reinstall torch-scatter -f https://data.pyg.org/whl/torch-2.4.1.html +``` + +### 1.4. Set environment variables + +For Apple Silicon devices (M-series chips) set fallback to CPU: +```bash +export MATTERGEN_DEVICE=cpu +export PYTORCH_ENABLE_MPS_FALLBACK=1; +``` + +## 2.0. Run example + +Set model name and results path: +```bash +export MODEL_NAME=chemical_system_energy_above_hull +export RESULTS_PATH="results/$MODEL_NAME/" +``` + +Run generation: +```bash +mattergen-generate $RESULTS_PATH --pretrained-name=$MODEL_NAME --batch_size=1 --properties_to_condition_on="{'chemical_system': 'Si-O'}" --diffusion_guidance_factor=2.0 +``` + +## 3.0. Results + +File structure expected to be like: +``` +results + chemical_system_energy_above_hull + generated_crystals.extxyz + generated_crystals_cif.zip + generated_trajectories.zip +``` + +Example structural output: +``` +8 +Lattice="4.810662746429443 0.0 2.003615617752075 2.0573911375230405 4.4635489819590255 1.6285755634307861 0.0 0.0 6.223104953765869" Properties=species:S:1:pos:R:3 pbc="T T T" +Si 3.19007697 0.64344807 2.15220843 +O 6.29417322 4.25980285 4.64711970 +Si 2.52538380 3.42031925 3.52259767 +O 6.28716089 4.28023109 7.76082322 +O 3.88651095 4.26880406 3.65002186 +O 2.86109621 2.03830726 2.83004283 +O 1.84533000 3.12136774 5.01444792 +O 3.87107245 0.94328279 6.87403968 +``` + +## 4.0. Run relaxation (optional) + +To relax the generated structures, you can use the [Relaxation Notebook](../mtrsm/relax_generated_material.ipynb). + +Copy the generated `extxyz` file to the `mtrsm/data/` folder and run the notebook. diff --git a/other/experiments/mtrgn/results/chemical_system_energy_above_hull/generated_crystals.extxyz b/other/experiments/mtrgn/results/chemical_system_energy_above_hull/generated_crystals.extxyz new file mode 100644 index 00000000..256a88d3 --- /dev/null +++ b/other/experiments/mtrgn/results/chemical_system_energy_above_hull/generated_crystals.extxyz @@ -0,0 +1,10 @@ +8 +Lattice="4.810662746429443 0.0 2.003615617752075 2.0573911375230405 4.4635489819590255 1.6285755634307861 0.0 0.0 6.223104953765869" Properties=species:S:1:pos:R:3 pbc="T T T" +Si 3.19007697 0.64344807 2.15220843 +O 6.29417322 4.25980285 4.64711970 +Si 2.52538380 3.42031925 3.52259767 +O 6.28716089 4.28023109 7.76082322 +O 3.88651095 4.26880406 3.65002186 +O 2.86109621 2.03830726 2.83004283 +O 1.84533000 3.12136774 5.01444792 +O 3.87107245 0.94328279 6.87403968 diff --git a/other/experiments/mtrgn/results/chemical_system_energy_above_hull/generated_crystals_cif.zip b/other/experiments/mtrgn/results/chemical_system_energy_above_hull/generated_crystals_cif.zip new file mode 100644 index 00000000..ef91cd65 Binary files /dev/null and b/other/experiments/mtrgn/results/chemical_system_energy_above_hull/generated_crystals_cif.zip differ diff --git a/other/experiments/mtrgn/results/chemical_system_energy_above_hull/generated_trajectories.zip b/other/experiments/mtrgn/results/chemical_system_energy_above_hull/generated_trajectories.zip new file mode 100644 index 00000000..0f0a3cab Binary files /dev/null and b/other/experiments/mtrgn/results/chemical_system_energy_above_hull/generated_trajectories.zip differ diff --git a/other/experiments/mtrsm/data/generated_crystals.extxyz b/other/experiments/mtrsm/data/generated_crystals.extxyz new file mode 100644 index 00000000..256a88d3 --- /dev/null +++ b/other/experiments/mtrsm/data/generated_crystals.extxyz @@ -0,0 +1,10 @@ +8 +Lattice="4.810662746429443 0.0 2.003615617752075 2.0573911375230405 4.4635489819590255 1.6285755634307861 0.0 0.0 6.223104953765869" Properties=species:S:1:pos:R:3 pbc="T T T" +Si 3.19007697 0.64344807 2.15220843 +O 6.29417322 4.25980285 4.64711970 +Si 2.52538380 3.42031925 3.52259767 +O 6.28716089 4.28023109 7.76082322 +O 3.88651095 4.26880406 3.65002186 +O 2.86109621 2.03830726 2.83004283 +O 1.84533000 3.12136774 5.01444792 +O 3.87107245 0.94328279 6.87403968 diff --git a/other/experiments/mtrsm/relax_generated_material.ipynb b/other/experiments/mtrsm/relax_generated_material.ipynb new file mode 100644 index 00000000..c8175152 --- /dev/null +++ b/other/experiments/mtrsm/relax_generated_material.ipynb @@ -0,0 +1,459 @@ +{ + "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": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:50.845136Z", + "start_time": "2025-10-07T01:31:50.840606Z" + } + }, + "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", + "\n", + " subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \".[forcefields]\", \"--quiet\"], check=False)\n", + " import mattersim" + ], + "outputs": [], + "execution_count": 56 + }, + { + "cell_type": "markdown", + "id": "ad71b3bcdb13e36a", + "metadata": {}, + "source": [ + "## 1. Prepare materials\n", + "### 1.1. Load material data" + ] + }, + { + "cell_type": "code", + "id": "2819d078b48216b9", + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:50.870937Z", + "start_time": "2025-10-07T01:31:50.862476Z" + } + }, + "source": [ + "from ase.io import read\n", + "from mat3ra.made.material import Material\n", + "from mat3ra.made.tools.convert import from_ase\n", + "\n", + "FOLDER = \"data\"\n", + "FILE_NAME = \"generated_crystals.extxyz\"\n", + "atoms = read(f\"{FOLDER}/{FILE_NAME}\")\n", + "\n", + "original_material = Material.create(from_ase(atoms))" + ], + "outputs": [], + "execution_count": 57 + }, + { + "cell_type": "markdown", + "id": "f011303e40ab0ee5", + "metadata": {}, + "source": [ + "### 1.2. Add modifications to material\n", + "Use any of the tools to modify the material, e.g. create supercell, add vacancy, add interstitials, etc.\n", + "Below is the example of creating a supercell and adding a vacancy." + ] + }, + { + "cell_type": "code", + "id": "b7e53d295d59fe89", + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:50.883280Z", + "start_time": "2025-10-07T01:31:50.880968Z" + } + }, + "source": [ + "# from mat3ra.made.tools.helpers import create_vacancy, create_supercell\n", + "\n", + "# supercell = create_supercell(original_material, scaling_factor=[2,2,2])\n", + "# material = create_vacancy(supercell, coordinate=[0.5, 0.5, 0.5], placement_method=\"closest_site\")" + ], + "outputs": [], + "execution_count": 58 + }, + { + "cell_type": "markdown", + "id": "45c3dade8bcd52b3", + "metadata": {}, + "source": [ + "## 1.3. Visualize materials" + ] + }, + { + "cell_type": "code", + "id": "4b91a2ae59c983a3", + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:50.922061Z", + "start_time": "2025-10-07T01:31:50.896821Z" + } + }, + "source": [ + "from utils.visualize import visualize_materials\n", + "\n", + "visualize_materials([material], rotation=\"-90x,-90y\")" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "GridBox(children=(VBox(children=(Label(value='O6Si2 - Material - rotation: -90x,-90y', layout=Layout(align_sel…" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "bd0b126365d24b58977ea27b0ea103d5" + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 59 + }, + { + "cell_type": "markdown", + "id": "8ce27a1c8864c29f", + "metadata": {}, + "source": [ + "## 2. Setup calculation\n", + "### 2.1. Convert to ASE atoms" + ] + }, + { + "cell_type": "code", + "id": "62b389e5458ce7c2", + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:50.938179Z", + "start_time": "2025-10-07T01:31:50.934787Z" + } + }, + "source": [ + "from mat3ra.made.tools.convert import to_ase\n", + "\n", + "original_material_atoms = to_ase(original_material)\n", + "material_atoms = to_ase(material)" + ], + "outputs": [], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "id": "c4c3b2a928a369ad", + "metadata": {}, + "source": [ + "### 2.2. Setup MatterSim calculator" + ] + }, + { + "cell_type": "code", + "id": "361cd269cb3e2db4", + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:51.142412Z", + "start_time": "2025-10-07T01:31:50.969024Z" + } + }, + "source": [ + "from mattersim.forcefield.potential import MatterSimCalculator\n", + "from mattersim.applications.relax import Relaxer\n", + "\n", + "original_material_atoms.calc = MatterSimCalculator()\n", + "material_atoms.calc = MatterSimCalculator()" + ], + "outputs": [], + "execution_count": 61 + }, + { + "cell_type": "markdown", + "id": "8119275fe9ffb1d8", + "metadata": {}, + "source": [ + "### 2.3. Relax structures" + ] + }, + { + "cell_type": "code", + "id": "48cbd2f29d0cbd2c", + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:52.917117Z", + "start_time": "2025-10-07T01:31:51.152702Z" + } + }, + "source": [ + "relaxer = Relaxer(optimizer=\"BFGS\", constrain_symmetry=True)\n", + "relaxer.relax(material_atoms, steps=500) # In-place relaxation\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Step Time Energy fmax\n", + "BFGS: 0 18:31:51 -51.711601 7.474610\n", + "BFGS: 1 18:31:51 -52.868916 3.378879\n", + "BFGS: 2 18:31:51 -53.223766 0.925829\n", + "BFGS: 3 18:31:51 -53.253685 0.452392\n", + "BFGS: 4 18:31:51 -53.267704 0.363445\n", + "BFGS: 5 18:31:51 -53.279449 0.310323\n", + "BFGS: 6 18:31:51 -53.286488 0.260276\n", + "BFGS: 7 18:31:51 -53.290512 0.309296\n", + "BFGS: 8 18:31:51 -53.295967 0.394289\n", + "BFGS: 9 18:31:51 -53.305187 1.008522\n", + "BFGS: 10 18:31:51 -53.322845 0.716170\n", + "BFGS: 11 18:31:51 -53.378014 0.674018\n", + "BFGS: 12 18:31:51 -53.508362 2.157271\n", + "BFGS: 13 18:31:51 -53.562679 0.714065\n", + "BFGS: 14 18:31:51 -53.587223 0.651299\n", + "BFGS: 15 18:31:51 -53.609467 0.720237\n", + "BFGS: 16 18:31:51 -53.688854 0.940445\n", + "BFGS: 17 18:31:51 -53.783585 1.254217\n", + "BFGS: 18 18:31:51 -53.885521 0.769957\n", + "BFGS: 19 18:31:51 -54.023678 1.609052\n", + "BFGS: 20 18:31:51 -53.990879 1.474999\n", + "BFGS: 21 18:31:51 -54.106972 0.703887\n", + "BFGS: 22 18:31:51 -54.162067 1.305980\n", + "BFGS: 23 18:31:51 -54.058495 3.763012\n", + "BFGS: 24 18:31:51 -54.210979 1.351347\n", + "BFGS: 25 18:31:51 -54.302280 1.049613\n", + "BFGS: 26 18:31:51 -54.332455 1.034705\n", + "BFGS: 27 18:31:51 -54.395729 1.066511\n", + "BFGS: 28 18:31:51 -54.447830 1.083045\n", + "BFGS: 29 18:31:51 -54.513798 1.170498\n", + "BFGS: 30 18:31:51 -54.566437 0.603935\n", + "BFGS: 31 18:31:51 -54.589157 0.582553\n", + "BFGS: 32 18:31:51 -54.627811 0.606264\n", + "BFGS: 33 18:31:51 -54.650311 0.382300\n", + "BFGS: 34 18:31:51 -54.672096 0.287184\n", + "BFGS: 35 18:31:51 -54.676777 0.277874\n", + "BFGS: 36 18:31:51 -54.683922 0.283365\n", + "BFGS: 37 18:31:52 -54.693722 0.396993\n", + "BFGS: 38 18:31:52 -54.713448 0.628270\n", + "BFGS: 39 18:31:52 -54.735531 0.748139\n", + "BFGS: 40 18:31:52 -54.763783 0.594354\n", + "BFGS: 41 18:31:52 -54.784546 0.326192\n", + "BFGS: 42 18:31:52 -54.791245 0.283903\n", + "BFGS: 43 18:31:52 -54.799938 0.308667\n", + "BFGS: 44 18:31:52 -54.807076 0.256395\n", + "BFGS: 45 18:31:52 -54.811127 0.165837\n", + "BFGS: 46 18:31:52 -54.813061 0.097924\n", + "BFGS: 47 18:31:52 -54.813824 0.071503\n", + "BFGS: 48 18:31:52 -54.814178 0.065386\n", + "BFGS: 49 18:31:52 -54.814941 0.077403\n", + "BFGS: 50 18:31:52 -54.815758 0.096490\n", + "BFGS: 51 18:31:52 -54.816650 0.106795\n", + "BFGS: 52 18:31:52 -54.817345 0.096437\n", + "BFGS: 53 18:31:52 -54.818039 0.086741\n", + "BFGS: 54 18:31:52 -54.818840 0.114829\n", + "BFGS: 55 18:31:52 -54.819641 0.100280\n", + "BFGS: 56 18:31:52 -54.820206 0.086753\n", + "BFGS: 57 18:31:52 -54.820549 0.062149\n", + "BFGS: 58 18:31:52 -54.820850 0.068862\n", + "BFGS: 59 18:31:52 -54.821152 0.068296\n", + "BFGS: 60 18:31:52 -54.821327 0.034591\n", + "BFGS: 61 18:31:52 -54.821373 0.011460\n", + "BFGS: 62 18:31:52 -54.821384 0.010631\n", + "BFGS: 63 18:31:52 -54.821396 0.012188\n", + "BFGS: 64 18:31:52 -54.821404 0.012625\n", + "BFGS: 65 18:31:52 -54.821415 0.010254\n", + "BFGS: 66 18:31:52 -54.821423 0.007155\n" + ] + }, + { + "data": { + "text/plain": [ + "(True,\n", + " MSONAtoms(symbols='SiOSiO5', pbc=True, cell=[[4.810662746141784, 1.3666731481439e-15, 2.0036156176167834], [2.0573911374447738, 4.463548981818283, 1.628575563353106], [1.8110774840280817e-16, 2.1009441273818866e-16, 6.223104953999998]], calculator=MatterSimCalculator(...)))" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "id": "116af57af6793bb", + "metadata": {}, + "source": [ + "### 2.4. Visualize relaxed structures" + ] + }, + { + "cell_type": "code", + "id": "6426cc56c5d51eef", + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:52.955069Z", + "start_time": "2025-10-07T01:31:52.921515Z" + } + }, + "source": [ + "from mat3ra.made.tools.convert import from_ase\n", + "\n", + "relaxed_material = Material.create(from_ase(material_atoms))\n", + "\n", + "visualize_materials([original_material, relaxed_material], rotation=\"-90x,-90y\")" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "GridBox(children=(VBox(children=(Label(value='O6Si2 - Material - rotation: -90x,-90y', layout=Layout(align_sel…" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "91f41765213d4f20a2c0ea5ae76581d6" + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "id": "7754f5d01964b082", + "metadata": {}, + "source": [ + "## 3. Calculate energy differences\n", + "\n", + "### 3.1. Get energies and atom counts" + ] + }, + { + "cell_type": "code", + "id": "2f4694776e7d1430", + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:53.025839Z", + "start_time": "2025-10-07T01:31:52.973533Z" + } + }, + "source": [ + "energy_relaxed = material_atoms.get_potential_energy()\n", + "energy_original = original_material_atoms.get_potential_energy()" + ], + "outputs": [], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "id": "baae670f86c9b639", + "metadata": {}, + "source": "### 3.2. Calculate energy difference" + }, + { + "cell_type": "code", + "id": "430936d099f5b816", + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:53.051618Z", + "start_time": "2025-10-07T01:31:53.048779Z" + } + }, + "source": [ + "e_difference = energy_relaxed - energy_original\n", + "print(f\"Energy difference: {e_difference} eV\")\n", + "\n", + "n_original = len(original_material_atoms)\n", + "n_relaxed = len(material_atoms)\n", + "\n", + "energy_original_per_atom = energy_original / n_original\n", + "energy_difference_per_atom = e_difference / n_relaxed\n", + "\n", + "print(f\"Energy difference per atom: {energy_difference_per_atom} eV/atom\")\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Energy difference: -3.109821319580078 eV\n", + "Energy difference per atom: -0.38872766494750977 eV/atom\n" + ] + } + ], + "execution_count": 65 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-10-07T01:31:53.094138Z", + "start_time": "2025-10-07T01:31:53.092325Z" + } + }, + "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 +}