AdsorbML tutorial#

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 Adsorbate, Bulk, Slab

bulk_src_id = "mp-30"
adsorbate_smiles = "*CO"

bulk = Bulk(bulk_src_id_from_db=bulk_src_id)
adsorbate = Adsorbate(adsorbate_smiles_from_db=adsorbate_smiles)
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.12/x64/lib/python3.12/site-packages/fairchem/data/oc/databases/pkls/bulks.pkl...

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 https://github.com/facebookresearch/fairchem/blob/main/src/fairchem/core/components/calculate/recipes/adsorbml.py#L316.

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-1p1")
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'.
       Step     Time          Energy          fmax
LBFGS:    0 21:46:54     -300.219297        0.047121
LBFGS:    1 21:46:54     -300.219795        0.045100
LBFGS:    2 21:46:54     -300.225582        0.004432
/home/runner/work/_tool/Python/3.12.12/x64/lib/python3.12/site-packages/fairchem/data/oc/core/adsorbate.py:89: UserWarning: An adsorbate with that SMILES string was not found. Choosing one at random instead.
  warnings.warn(
       Step     Time          Energy          fmax
LBFGS:    0 21:46:55     -329.009718        2.969513
LBFGS:    1 21:46:55     -329.262835        1.461637
LBFGS:    2 21:46:55     -329.394583        0.970980
LBFGS:    3 21:46:55     -329.437777        0.865683
LBFGS:    4 21:46:56     -329.510420        0.710857
LBFGS:    5 21:46:56     -329.535750        0.527360
LBFGS:    6 21:46:56     -329.547661        0.368447
LBFGS:    7 21:46:56     -329.559611        0.412708
LBFGS:    8 21:46:56     -329.577611        0.612601
LBFGS:    9 21:46:56     -329.603838        0.625865
LBFGS:   10 21:46:57     -329.627183        0.542668
LBFGS:   11 21:46:57     -329.650073        0.598594
LBFGS:   12 21:46:57     -329.681866        0.556497
LBFGS:   13 21:46:57     -329.724484        0.898908
LBFGS:   14 21:46:57     -329.774586        1.075287
LBFGS:   15 21:46:58     -329.824795        0.864786
LBFGS:   16 21:46:58     -329.859658        0.402742
LBFGS:   17 21:46:58     -329.880383        0.496829
LBFGS:   18 21:46:58     -329.913306        0.741736
LBFGS:   19 21:46:58     -329.952435        0.843978
LBFGS:   20 21:46:58     -329.978150        0.517978
       Step     Time          Energy          fmax
LBFGS:    0 21:46:59     -328.863083        3.004484
LBFGS:    1 21:46:59     -329.128964        1.449172
LBFGS:    2 21:46:59     -329.297528        1.136904
LBFGS:    3 21:46:59     -329.349667        1.035495
LBFGS:    4 21:46:59     -329.443001        0.754110
LBFGS:    5 21:47:00     -329.470620        0.464107
LBFGS:    6 21:47:00     -329.485615        0.474592
LBFGS:    7 21:47:00     -329.507041        0.504846
LBFGS:    8 21:47:00     -329.534361        0.710275
LBFGS:    9 21:47:00     -329.564253        0.611046
LBFGS:   10 21:47:00     -329.587145        0.594285
LBFGS:   11 21:47:01     -329.618104        0.757982
LBFGS:   12 21:47:01     -329.666064        0.844110
LBFGS:   13 21:47:01     -329.731732        0.960181
LBFGS:   14 21:47:01     -329.812541        1.099778
LBFGS:   15 21:47:01     -329.892550        0.743099
LBFGS:   16 21:47:02     -329.941872        0.452439
LBFGS:   17 21:47:02     -329.968739        0.471621
LBFGS:   18 21:47:02     -329.997164        0.399778
LBFGS:   19 21:47:02     -330.011504        0.930872
LBFGS:   20 21:47:02     -330.021836        0.582177
       Step     Time          Energy          fmax
LBFGS:    0 21:47:02     -329.256671        2.819493
LBFGS:    1 21:47:03     -329.460396        1.434213
LBFGS:    2 21:47:03     -329.578000        0.942242
LBFGS:    3 21:47:03     -329.612790        0.876027
LBFGS:    4 21:47:03     -329.669688        0.456015
LBFGS:    5 21:47:03     -329.683714        0.335062
LBFGS:    6 21:47:04     -329.692032        0.361890
LBFGS:    7 21:47:04     -329.702544        0.349888
LBFGS:    8 21:47:04     -329.719117        0.538381
LBFGS:    9 21:47:04     -329.736924        0.499436
LBFGS:   10 21:47:04     -329.751364        0.440202
LBFGS:   11 21:47:04     -329.768120        0.522402
LBFGS:   12 21:47:05     -329.793057        0.593160
LBFGS:   13 21:47:05     -329.825993        0.699350
LBFGS:   14 21:47:05     -329.863444        0.737213
LBFGS:   15 21:47:05     -329.897252        0.451647
LBFGS:   16 21:47:05     -329.919163        0.308380
LBFGS:   17 21:47:06     -329.939778        0.458390
LBFGS:   18 21:47:06     -329.970366        0.587978
LBFGS:   19 21:47:06     -329.996237        0.462109
LBFGS:   20 21:47:06     -330.011389        0.346907
       Step     Time          Energy          fmax
LBFGS:    0 21:47:06     -329.205531        2.770491
LBFGS:    1 21:47:06     -329.425763        1.349018
LBFGS:    2 21:47:07     -329.544644        0.934491
LBFGS:    3 21:47:07     -329.576283        0.841549
LBFGS:    4 21:47:07     -329.634005        0.618345
LBFGS:    5 21:47:07     -329.649132        0.403414
LBFGS:    6 21:47:07     -329.658309        0.343094
LBFGS:    7 21:47:08     -329.670216        0.412081
LBFGS:    8 21:47:08     -329.686520        0.494493
LBFGS:    9 21:47:08     -329.702445        0.360547
LBFGS:   10 21:47:08     -329.715130        0.422155
LBFGS:   11 21:47:08     -329.731499        0.524059
LBFGS:   12 21:47:08     -329.758107        0.593420
LBFGS:   13 21:47:09     -329.797146        0.846435
LBFGS:   14 21:47:09     -329.845614        0.867897
LBFGS:   15 21:47:09     -329.893467        0.532809
LBFGS:   16 21:47:09     -329.922968        0.297055
LBFGS:   17 21:47:09     -329.944394        0.413095
LBFGS:   18 21:47:10     -329.975649        0.534590
LBFGS:   19 21:47:10     -330.004641        0.488136
LBFGS:   20 21:47:10     -330.024418        0.446677
       Step     Time          Energy          fmax
LBFGS:    0 21:47:10     -329.211249        2.539020
LBFGS:    1 21:47:10     -329.424616        1.304845
LBFGS:    2 21:47:10     -329.546055        0.967964
LBFGS:    3 21:47:11     -329.582858        0.843349
LBFGS:    4 21:47:11     -329.649563        0.715530
LBFGS:    5 21:47:11     -329.668446        0.470580
LBFGS:    6 21:47:11     -329.680205        0.335363
LBFGS:    7 21:47:11     -329.694857        0.424200
LBFGS:    8 21:47:12     -329.717118        0.593556
LBFGS:    9 21:47:12     -329.741145        0.510447
LBFGS:   10 21:47:12     -329.759760        0.553055
LBFGS:   11 21:47:12     -329.783663        0.671016
LBFGS:   12 21:47:12     -329.818923        0.717836
LBFGS:   13 21:47:12     -329.866856        0.852108
LBFGS:   14 21:47:13     -329.926051        0.900685
LBFGS:   15 21:47:13     -329.983862        0.579024
LBFGS:   16 21:47:13     -330.014618        0.273163
LBFGS:   17 21:47:13     -330.030867        0.295784
LBFGS:   18 21:47:13     -330.050559        0.346542
LBFGS:   19 21:47:14     -330.073609        0.690590
LBFGS:   20 21:47:14     -330.085297        0.532002
       Step     Time          Energy          fmax
LBFGS:    0 21:47:14     -329.135079        2.582889
LBFGS:    1 21:47:14     -329.367688        1.265372
LBFGS:    2 21:47:14     -329.494570        1.086841
LBFGS:    3 21:47:14     -329.540062        0.986831
LBFGS:    4 21:47:15     -329.625924        0.962412
LBFGS:    5 21:47:15     -329.667471        0.662273
LBFGS:    6 21:47:15     -329.689778        0.509100
LBFGS:    7 21:47:15     -329.717728        0.575150
LBFGS:    8 21:47:15     -329.760651        0.709038
LBFGS:    9 21:47:16     -329.811247        0.742584
LBFGS:   10 21:47:16     -329.849528        0.627490
LBFGS:   11 21:47:16     -329.893954        0.795599
LBFGS:   12 21:47:16     -329.935393        0.857905
LBFGS:   13 21:47:16     -329.992936        0.844200
LBFGS:   14 21:47:16     -330.053818        0.867204
LBFGS:   15 21:47:17     -330.108365        0.605143
LBFGS:   16 21:47:17     -330.132166        0.436533
LBFGS:   17 21:47:17     -330.136269        0.502194
LBFGS:   18 21:47:17     -330.148589        0.282005
LBFGS:   19 21:47:17     -330.156357        0.200729
LBFGS:   20 21:47:18     -330.171822        0.240531
       Step     Time          Energy          fmax
LBFGS:    0 21:47:18     -328.733914        3.200605
LBFGS:    1 21:47:18     -328.991669        1.490292
LBFGS:    2 21:47:18     -329.154740        1.069548
LBFGS:    3 21:47:18     -329.214297        1.158683
LBFGS:    4 21:47:19     -329.306170        0.880184
LBFGS:    5 21:47:19     -329.354767        0.521454
LBFGS:    6 21:47:19     -329.373812        0.406390
LBFGS:    7 21:47:19     -329.392214        0.423460
LBFGS:    8 21:47:19     -329.424117        0.793888
LBFGS:    9 21:47:19     -329.471205        0.983893
LBFGS:   10 21:47:20     -329.517491        0.720455
LBFGS:   11 21:47:20     -329.554768        0.678971
LBFGS:   12 21:47:20     -329.605509        0.670629
LBFGS:   13 21:47:20     -329.668789        1.013265
LBFGS:   14 21:47:20     -329.743601        1.208167
LBFGS:   15 21:47:21     -329.825650        1.019916
LBFGS:   16 21:47:21     -329.894021        0.502819
LBFGS:   17 21:47:21     -329.929637        0.549779
LBFGS:   18 21:47:21     -329.969439        0.774830
LBFGS:   19 21:47:21     -330.012402        0.637313
LBFGS:   20 21:47:21     -330.041697        0.635758
       Step     Time          Energy          fmax
LBFGS:    0 21:47:22     -328.812857        3.139527
LBFGS:    1 21:47:22     -329.104132        1.659777
LBFGS:    2 21:47:22     -329.261296        1.063189
LBFGS:    3 21:47:22     -329.315386        0.941084
LBFGS:    4 21:47:22     -329.401923        0.762253
LBFGS:    5 21:47:23     -329.432641        0.585092
LBFGS:    6 21:47:23     -329.447833        0.387286
LBFGS:    7 21:47:23     -329.464140        0.482908
LBFGS:    8 21:47:23     -329.488940        0.753902
LBFGS:    9 21:47:23     -329.530215        0.830495
LBFGS:   10 21:47:23     -329.567839        0.643488
LBFGS:   11 21:47:24     -329.601157        0.690262
LBFGS:   12 21:47:24     -329.642043        0.614279
LBFGS:   13 21:47:24     -329.693686        0.974798
LBFGS:   14 21:47:24     -329.754916        1.237348
LBFGS:   15 21:47:24     -329.820443        1.103436
LBFGS:   16 21:47:25     -329.870162        0.439190
LBFGS:   17 21:47:25     -329.893597        0.480279
LBFGS:   18 21:47:25     -329.922293        0.646482
LBFGS:   19 21:47:25     -329.961436        0.807308
LBFGS:   20 21:47:25     -329.985352        0.502231
       Step     Time          Energy          fmax
LBFGS:    0 21:47:25     -329.314454        2.736768
LBFGS:    1 21:47:26     -329.518336        1.399365
LBFGS:    2 21:47:26     -329.630576        0.889362
LBFGS:    3 21:47:26     -329.660500        0.798830
LBFGS:    4 21:47:26     -329.712325        0.471946
LBFGS:    5 21:47:26     -329.722416        0.285261
LBFGS:    6 21:47:27     -329.729027        0.291240
LBFGS:    7 21:47:27     -329.737359        0.353125
LBFGS:    8 21:47:27     -329.748875        0.425774
LBFGS:    9 21:47:27     -329.759108        0.313418
LBFGS:   10 21:47:27     -329.767609        0.363709
LBFGS:   11 21:47:28     -329.779276        0.441897
LBFGS:   12 21:47:28     -329.798659        0.552644
LBFGS:   13 21:47:28     -329.826346        0.683711
LBFGS:   14 21:47:28     -329.857178        0.620598
LBFGS:   15 21:47:28     -329.881241        0.312385
LBFGS:   16 21:47:28     -329.894892        0.283758
LBFGS:   17 21:47:29     -329.911227        0.489755
LBFGS:   18 21:47:29     -329.941632        0.716179
LBFGS:   19 21:47:29     -329.974209        0.678464
LBFGS:   20 21:47:29     -329.992068        0.306017
       Step     Time          Energy          fmax
LBFGS:    0 21:47:29     -329.228388        2.918154
LBFGS:    1 21:47:30     -329.437794        1.484229
LBFGS:    2 21:47:30     -329.555562        0.932674
LBFGS:    3 21:47:30     -329.590762        0.872411
LBFGS:    4 21:47:30     -329.650158        0.486961
LBFGS:    5 21:47:30     -329.665318        0.335102
LBFGS:    6 21:47:30     -329.674773        0.327722
LBFGS:    7 21:47:31     -329.686375        0.376791
LBFGS:    8 21:47:31     -329.703898        0.557246
LBFGS:    9 21:47:31     -329.722813        0.502467
LBFGS:   10 21:47:31     -329.738278        0.468261
LBFGS:   11 21:47:31     -329.756323        0.529000
LBFGS:   12 21:47:32     -329.783696        0.643280
LBFGS:   13 21:47:32     -329.821881        0.804498
LBFGS:   14 21:47:32     -329.866307        0.804888
LBFGS:   15 21:47:32     -329.906361        0.506098
LBFGS:   16 21:47:32     -329.928643        0.354990
LBFGS:   17 21:47:32     -329.945223        0.405429
LBFGS:   18 21:47:33     -329.975018        0.566666
LBFGS:   19 21:47:33     -330.004456        0.510405
LBFGS:   20 21:47:33     -330.020987        0.304343
top_candidates = outputs["adslabs"]
global_min_candidate = top_candidates[0]
top_candidates = outputs["adslabs"]
pd.DataFrame(top_candidates)
input_atoms atoms results
0 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.17182211893726, 'forces': [[0....
1 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0852971555586, 'forces': [[0.0...
2 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.02441840189624, 'forces': [[0....
3 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0218358518474, 'forces': [[0.0...
4 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0209870817058, 'forces': [[0.0...
5 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.01138930338556, 'forces': [[0....
6 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.99206786173517, 'forces': [[0....
7 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.985352087199, 'forces': [[0.0,...
8 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.97814993876153, 'forces': [[0....

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}/")