Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

AdsorbML Tutorial

Tutorial Overview
PropertyValue
DifficultyIntermediate
Time20-30 minutes
PrerequisitesBasic Python, ASE
GoalFind optimal adsorption sites using ML-accelerated relaxations

The AdsorbML paper showed that pre-trained machine learning potentials were now viable to find and prioritize the best adsorption sites for a given surface. The results were quite impressive, especially if you were willing to do a DFT single-point calculation on the best calculations.

The latest UMA models are now total-energy models, and the results for the adsorption energy are even more impressive (see the paper for details and benchmarks). The AdsorbML package helps you with automated multi-adsorbate placement, and will automatically run calculations using the ML models to find the best sites to sample.

Define desired adsorbate+slab system

from __future__ import annotations

import pandas as pd
from fairchem.data.oc.core import Bulk, Slab, Adsorbate
from ase.build import molecule

co_molecule = molecule("CO")
adsorbate = Adsorbate(adsorbate_atoms=co_molecule, adsorbate_binding_indices=[1]) # 1 corresponds to the carbon atom
# adsorbate = [Adsorbate(adsorbate_atoms=co_molecule, adsorbate_binding_indices=[1]) for _ in range(2)] # 2 COs

bulk_src_id = "mp-30"
bulk = Bulk(bulk_src_id_from_db=bulk_src_id)
slabs = Slab.from_bulk_get_specific_millers(bulk=bulk, specific_millers=(1, 1, 1))

# There may be multiple slabs with this miller index.
# For demonstrative purposes we will take the first entry.
slab = slabs[0]
Downloading /home/runner/work/_tool/Python/3.12.14/x64/lib/python3.12/site-packages/fairchem/data/oc/databases/pkls/bulks.pkl...
/home/runner/work/_tool/Python/3.12.14/x64/lib/python3.12/site-packages/fairchem/data/oc/core/bulk.py:66: UserWarning: Loading data from a pickle file. Pickle files can execute arbitrary code and should only be loaded from trusted sources. Consider migrating to a safer format such as Parquet, CSV, or JSON.
  bulk_db = safe_pickle_load(fp)

Run heuristic/random adsorbate placement and ML relaxations

Now that we’ve defined the bulk, slab, and adsorbates of interest, we can quickly use the pre-trained UMA model as a calculator and the helper script fairchem.core.components.calculate.recipes.adsorbml.run_adsorbml. More details on the automated pipeline can be found at src/fairchem/core/components/calculate/recipes/adsorbml.py.

from ase.optimize import LBFGS
from fairchem.core import FAIRChemCalculator, pretrained_mlip
from fairchem.core.components.calculate.recipes.adsorbml import run_adsorbml

predictor = pretrained_mlip.get_predict_unit("uma-s-1p2")
calc = FAIRChemCalculator(predictor, task_name="oc20")

outputs = run_adsorbml(
    slab=slab,
    adsorbate=adsorbate,
    calculator=calc,
    optimizer_cls=LBFGS,
    fmax=0.02,
    steps=20,  # Increase to 200 for practical application, 20 is used for demonstrations
    num_placements=10,  # Increase to 100 for practical application, 10 is used for demonstrations
    reference_ml_energies=True,  # True if using a total energy model (i.e. UMA)
    relaxed_slab_atoms=None,
    place_on_relaxed_slab=False,
)
WARNING:root:device was not explicitly set, using device='cuda'.
WARNING:root:Model is being compiled this might take a while for the first time
W0820 00:02:45.556000 10172 site-packages/torch/_logging/_internal.py:1345] [0/0] Profiler record function <class 'torch.autograd.profiler.record_function'> will be ignored
       Step     Time          Energy          fmax
LBFGS:    0 00:03:23     -300.206730        0.046073
LBFGS:    1 00:03:23     -300.207208        0.044108
LBFGS:    2 00:03:23     -300.212885        0.005262
WARNING:root:The UMA fast path (merge_mole + compile) is only available for fixed composition, task, charge, and spin. This is optimized for MD applications. Falling back to a less optimized version for subsequent evaluations. Reason: 'Compositions differ from merged model'.
Use inference_settings='batch' for heterogeneous batched evaluations.
       Step     Time          Energy          fmax
LBFGS:    0 00:03:29     -314.795151        2.141435
LBFGS:    1 00:03:29     -314.788147        2.881827
LBFGS:    2 00:03:29     -314.839770        0.952721
LBFGS:    3 00:03:29     -314.877308        1.181137
LBFGS:    4 00:03:30     -314.989675        2.018461
LBFGS:    5 00:03:30     -314.885770        3.109859
LBFGS:    6 00:03:30     -315.028829        0.883008
LBFGS:    7 00:03:30     -315.041561        0.427447
LBFGS:    8 00:03:30     -315.054959        1.149868
LBFGS:    9 00:03:31     -315.062126        0.904128
LBFGS:   10 00:03:31     -315.088884        0.610403
LBFGS:   11 00:03:31     -315.094913        0.504053
LBFGS:   12 00:03:31     -315.100555        0.184233
LBFGS:   13 00:03:31     -315.103668        0.119296
LBFGS:   14 00:03:31     -315.104937        0.195411
LBFGS:   15 00:03:32     -315.105850        0.107672
LBFGS:   16 00:03:32     -315.107374        0.179243
LBFGS:   17 00:03:32     -315.108864        0.094124
LBFGS:   18 00:03:32     -315.109316        0.046202
LBFGS:   19 00:03:32     -315.109510        0.046738
LBFGS:   20 00:03:33     -315.109873        0.073836
       Step     Time          Energy          fmax
LBFGS:    0 00:03:33     -314.839568        1.806109
LBFGS:    1 00:03:33     -314.847735        2.495789
LBFGS:    2 00:03:33     -314.896391        1.204814
LBFGS:    3 00:03:34     -315.009755        1.994791
LBFGS:    4 00:03:34     -315.066341        1.378407
LBFGS:    5 00:03:34     -315.088557        0.734303
LBFGS:    6 00:03:34     -315.095477        0.321336
LBFGS:    7 00:03:34     -315.101786        0.616317
LBFGS:    8 00:03:34     -315.107855        0.858086
LBFGS:    9 00:03:35     -315.118674        0.959319
LBFGS:   10 00:03:35     -315.126008        0.559488
LBFGS:   11 00:03:35     -315.128587        0.082845
LBFGS:   12 00:03:35     -315.128990        0.113969
LBFGS:   13 00:03:35     -315.129660        0.145983
LBFGS:   14 00:03:36     -315.130551        0.164545
LBFGS:   15 00:03:36     -315.131619        0.152425
LBFGS:   16 00:03:36     -315.132402        0.093404
LBFGS:   17 00:03:36     -315.132869        0.062023
LBFGS:   18 00:03:36     -315.133302        0.088240
LBFGS:   19 00:03:37     -315.134145        0.131644
LBFGS:   20 00:03:37     -315.135289        0.127600
       Step     Time          Energy          fmax
LBFGS:    0 00:03:37     -314.833525        1.828196
LBFGS:    1 00:03:37     -314.840664        2.517151
LBFGS:    2 00:03:37     -314.888976        1.177600
LBFGS:    3 00:03:38     -314.993003        1.923850
LBFGS:    4 00:03:38     -315.061731        1.473445
LBFGS:    5 00:03:38     -315.083262        0.780882
LBFGS:    6 00:03:38     -315.091338        0.334415
LBFGS:    7 00:03:38     -315.098086        0.679623
LBFGS:    8 00:03:39     -315.104908        0.941925
LBFGS:    9 00:03:39     -315.116412        1.018206
LBFGS:   10 00:03:39     -315.124693        0.574915
LBFGS:   11 00:03:39     -315.127462        0.078062
LBFGS:   12 00:03:39     -315.127917        0.105447
LBFGS:   13 00:03:40     -315.128520        0.134142
LBFGS:   14 00:03:40     -315.129371        0.153290
LBFGS:   15 00:03:40     -315.130353        0.144076
LBFGS:   16 00:03:40     -315.131071        0.091380
LBFGS:   17 00:03:40     -315.131486        0.061076
LBFGS:   18 00:03:40     -315.131872        0.084566
LBFGS:   19 00:03:41     -315.132625        0.127209
LBFGS:   20 00:03:41     -315.133724        0.133337
       Step     Time          Energy          fmax
LBFGS:    0 00:03:41     -314.881036        2.459260
LBFGS:    1 00:03:41     -314.869444        3.261945
LBFGS:    2 00:03:41     -314.932475        1.059515
LBFGS:    3 00:03:42     -314.966089        1.061219
LBFGS:    4 00:03:42     -315.038198        2.115853
LBFGS:    5 00:03:42     -315.070924        1.057594
LBFGS:    6 00:03:42     -315.083711        0.541704
LBFGS:    7 00:03:42     -315.087506        0.229829
LBFGS:    8 00:03:43     -315.091312        0.527931
LBFGS:    9 00:03:43     -315.097288        0.814269
LBFGS:   10 00:03:43     -315.103804        0.809236
LBFGS:   11 00:03:43     -315.109224        0.442681
LBFGS:   12 00:03:44     -315.112197        0.205209
LBFGS:   13 00:03:44     -315.114687        0.433564
LBFGS:   14 00:03:44     -315.120573        0.702890
LBFGS:   15 00:03:44     -315.127074        0.585852
LBFGS:   16 00:03:45     -315.130527        0.318755
LBFGS:   17 00:03:45     -315.132831        0.121408
LBFGS:   18 00:03:45     -315.133996        0.242746
LBFGS:   19 00:03:45     -315.136237        0.431881
LBFGS:   20 00:03:46     -315.138227        0.435438
       Step     Time          Energy          fmax
LBFGS:    0 00:03:46     -314.867245        2.197945
LBFGS:    1 00:03:46     -314.863473        3.012733
LBFGS:    2 00:03:46     -314.917632        1.110596
LBFGS:    3 00:03:47     -314.962829        1.280575
LBFGS:    4 00:03:47     -315.040137        2.305654
LBFGS:    5 00:03:47     -315.064714        0.967377
LBFGS:    6 00:03:47     -315.074421        0.262404
LBFGS:    7 00:03:47     -315.076378        0.238676
LBFGS:    8 00:03:48     -315.081074        0.602019
LBFGS:    9 00:03:48     -315.086563        0.760829
LBFGS:   10 00:03:48     -315.091335        0.569925
LBFGS:   11 00:03:48     -315.093951        0.166796
LBFGS:   12 00:03:49     -315.095035        0.170100
LBFGS:   13 00:03:49     -315.096561        0.352913
LBFGS:   14 00:03:49     -315.098833        0.429236
LBFGS:   15 00:03:49     -315.100409        0.273791
LBFGS:   16 00:03:50     -315.101003        0.086310
LBFGS:   17 00:03:50     -315.101326        0.095442
LBFGS:   18 00:03:50     -315.101724        0.181930
LBFGS:   19 00:03:50     -315.102373        0.249166
LBFGS:   20 00:03:50     -315.103024        0.206844
       Step     Time          Energy          fmax
LBFGS:    0 00:03:51     -314.794139        1.701399
LBFGS:    1 00:03:51     -314.801738        2.310896
LBFGS:    2 00:03:51     -314.847433        1.088776
LBFGS:    3 00:03:51     -314.969067        1.861006
LBFGS:    4 00:03:52     -314.985933        2.016199
LBFGS:    5 00:03:52     -315.054492        1.078070
LBFGS:    6 00:03:52     -315.075144        0.527856
LBFGS:    7 00:03:52     -315.087690        0.946278
LBFGS:    8 00:03:53     -315.095304        0.845737
LBFGS:    9 00:03:53     -315.123880        1.060214
LBFGS:   10 00:03:53     -315.129301        0.315231
LBFGS:   11 00:03:53     -315.132639        0.161225
LBFGS:   12 00:03:54     -315.134736        0.062456
LBFGS:   13 00:03:54     -315.135128        0.109153
LBFGS:   14 00:03:54     -315.135703        0.121159
LBFGS:   15 00:03:54     -315.136708        0.142136
LBFGS:   16 00:03:54     -315.137601        0.112161
LBFGS:   17 00:03:55     -315.138086        0.059253
LBFGS:   18 00:03:55     -315.138317        0.052706
LBFGS:   19 00:03:55     -315.138589        0.088571
LBFGS:   20 00:03:55     -315.139083        0.128517
       Step     Time          Energy          fmax
LBFGS:    0 00:03:56     -314.847801        1.832425
LBFGS:    1 00:03:56     -314.855084        2.552221
LBFGS:    2 00:03:56     -314.904020        1.197462
LBFGS:    3 00:03:57     -315.004790        1.933244
LBFGS:    4 00:03:57     -315.070808        1.598955
LBFGS:    5 00:03:57     -315.088254        0.687507
LBFGS:    6 00:03:57     -315.093830        0.291513
LBFGS:    7 00:03:57     -315.097342        0.483570
LBFGS:    8 00:03:58     -315.106470        0.922817
LBFGS:    9 00:03:58     -315.112914        0.840566
LBFGS:   10 00:03:58     -315.119329        0.249249
LBFGS:   11 00:03:58     -315.120234        0.102416
LBFGS:   12 00:03:59     -315.120843        0.179477
LBFGS:   13 00:03:59     -315.122037        0.258455
LBFGS:   14 00:03:59     -315.123395        0.267755
LBFGS:   15 00:03:59     -315.124548        0.193375
LBFGS:   16 00:04:00     -315.125260        0.074779
LBFGS:   17 00:04:00     -315.125747        0.106820
LBFGS:   18 00:04:00     -315.126529        0.192951
LBFGS:   19 00:04:00     -315.127904        0.265678
LBFGS:   20 00:04:00     -315.129379        0.206774
       Step     Time          Energy          fmax
LBFGS:    0 00:04:00     -314.858578        1.744814
LBFGS:    1 00:04:01     -314.868655        2.450327
LBFGS:    2 00:04:01     -314.917941        1.256103
LBFGS:    3 00:04:01     -315.046627        2.118288
LBFGS:    4 00:04:01     -315.085064        1.179875
LBFGS:    5 00:04:02     -315.100788        0.498896
LBFGS:    6 00:04:02     -315.104128        0.229944
LBFGS:    7 00:04:02     -315.108122        0.482630
LBFGS:    8 00:04:02     -315.113478        0.739707
LBFGS:    9 00:04:03     -315.119856        0.760964
LBFGS:   10 00:04:03     -315.124792        0.383159
LBFGS:   11 00:04:03     -315.126086        0.100398
LBFGS:   12 00:04:03     -315.126522        0.178109
LBFGS:   13 00:04:03     -315.128075        0.328638
LBFGS:   14 00:04:03     -315.129582        0.345247
LBFGS:   15 00:04:04     -315.130948        0.230827
LBFGS:   16 00:04:04     -315.131725        0.075075
LBFGS:   17 00:04:04     -315.132279        0.116915
LBFGS:   18 00:04:04     -315.133168        0.222019
LBFGS:   19 00:04:04     -315.134528        0.283336
LBFGS:   20 00:04:05     -315.135706        0.196212
       Step     Time          Energy          fmax
LBFGS:    0 00:04:05     -314.866754        2.417548
LBFGS:    1 00:04:05     -314.855054        3.216168
LBFGS:    2 00:04:05     -314.914733        1.042271
LBFGS:    3 00:04:05     -314.946058        1.058496
LBFGS:    4 00:04:05     -315.019227        2.146320
LBFGS:    5 00:04:06     -315.046663        1.076485
LBFGS:    6 00:04:06     -315.063893        0.617089
LBFGS:    7 00:04:06     -315.068479        0.244851
LBFGS:    8 00:04:06     -315.073800        0.596252
LBFGS:    9 00:04:06     -315.079006        0.825980
LBFGS:   10 00:04:07     -315.086693        0.847972
LBFGS:   11 00:04:07     -315.092215        0.468035
LBFGS:   12 00:04:07     -315.094490        0.114353
LBFGS:   13 00:04:07     -315.095488        0.231907
LBFGS:   14 00:04:08     -315.098061        0.381957
LBFGS:   15 00:04:08     -315.100005        0.321651
LBFGS:   16 00:04:08     -315.101021        0.174638
LBFGS:   17 00:04:08     -315.101487        0.074494
LBFGS:   18 00:04:09     -315.101850        0.109561
LBFGS:   19 00:04:09     -315.102462        0.198176
LBFGS:   20 00:04:09     -315.103300        0.223711
       Step     Time          Energy          fmax
LBFGS:    0 00:04:09     -314.993121        3.211945
LBFGS:    1 00:04:09     -314.958909        3.870610
LBFGS:    2 00:04:10     -315.053432        1.067796
LBFGS:    3 00:04:10     -315.071750        0.762625
LBFGS:    4 00:04:10     -315.104609        1.423780
LBFGS:    5 00:04:10     -315.155715        1.238123
LBFGS:    6 00:04:11     -315.164691        0.477639
LBFGS:    7 00:04:11     -315.168855        0.215178
LBFGS:    8 00:04:11     -315.171135        0.387314
LBFGS:    9 00:04:11     -315.175419        0.539183
LBFGS:   10 00:04:11     -315.178451        0.409494
LBFGS:   11 00:04:12     -315.180238        0.135609
LBFGS:   12 00:04:12     -315.181305        0.178544
LBFGS:   13 00:04:12     -315.183034        0.356822
LBFGS:   14 00:04:12     -315.185654        0.454331
LBFGS:   15 00:04:13     -315.188188        0.368485
LBFGS:   16 00:04:13     -315.189372        0.139793
LBFGS:   17 00:04:13     -315.189845        0.057130
LBFGS:   18 00:04:13     -315.190238        0.137840
LBFGS:   19 00:04:13     -315.190932        0.228696
LBFGS:   20 00:04:14     -315.191768        0.228948
top_candidates = outputs["adslabs"]
global_min_candidate = top_candidates[0]
top_candidates = outputs["adslabs"]
pd.DataFrame(top_candidates)
Loading...

Write VASP input files

If you want to verify the results, you should run VASP. This assumes you have access to VASP pseudopotentials. The default VASP flags (which are equivalent to those used to make OC20) are located in ocdata.utils.vasp. Alternatively, you may pass your own vasp flags to the write_vasp_input_files function as vasp_flags. Note that to run this you need access to the VASP pseudopotentials and need to have those set up in ASE.

import os

from fairchem.data.oc.utils.vasp import write_vasp_input_files

# Grab the 5 systems with the lowest energy
top_5_candidates = top_candidates[:5]

# Write the inputs
for idx, config in enumerate(top_5_candidates):
    os.makedirs(f"data/{idx}", exist_ok=True)
    write_vasp_input_files(config["atoms"], outdir=f"data/{idx}/")