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/fairchem/fairchem/src/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 17:33:09     -300.219299        0.047121
LBFGS:    1 17:33:09     -300.219793        0.045100
LBFGS:    2 17:33:09     -300.225584        0.004432
/home/runner/work/fairchem/fairchem/src/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 17:33:10     -329.009720        2.969513
LBFGS:    1 17:33:10     -329.262831        1.461637
LBFGS:    2 17:33:10     -329.394587        0.970977
LBFGS:    3 17:33:11     -329.437779        0.865701
LBFGS:    4 17:33:11     -329.510418        0.710860
LBFGS:    5 17:33:11     -329.535739        0.527390
LBFGS:    6 17:33:11     -329.547667        0.368418
LBFGS:    7 17:33:11     -329.559617        0.412728
LBFGS:    8 17:33:11     -329.577612        0.612677
LBFGS:    9 17:33:12     -329.603833        0.625826
LBFGS:   10 17:33:12     -329.627177        0.542610
LBFGS:   11 17:33:12     -329.650065        0.598560
LBFGS:   12 17:33:12     -329.681853        0.556428
LBFGS:   13 17:33:12     -329.724476        0.898936
LBFGS:   14 17:33:13     -329.774575        1.075349
LBFGS:   15 17:33:13     -329.824790        0.864918
LBFGS:   16 17:33:13     -329.859664        0.402840
LBFGS:   17 17:33:13     -329.880385        0.496813
LBFGS:   18 17:33:13     -329.913312        0.741539
LBFGS:   19 17:33:14     -329.952433        0.843938
LBFGS:   20 17:33:14     -329.978140        0.517958
       Step     Time          Energy          fmax
LBFGS:    0 17:33:14     -328.863085        3.004485
LBFGS:    1 17:33:14     -329.128962        1.449172
LBFGS:    2 17:33:14     -329.297514        1.136809
LBFGS:    3 17:33:14     -329.349667        1.035450
LBFGS:    4 17:33:15     -329.442965        0.754513
LBFGS:    5 17:33:15     -329.470618        0.464068
LBFGS:    6 17:33:15     -329.485610        0.474615
LBFGS:    7 17:33:15     -329.507020        0.504462
LBFGS:    8 17:33:16     -329.534342        0.710317
LBFGS:    9 17:33:16     -329.564230        0.611189
LBFGS:   10 17:33:16     -329.587126        0.594134
LBFGS:   11 17:33:16     -329.618073        0.757973
LBFGS:   12 17:33:16     -329.666016        0.844172
LBFGS:   13 17:33:17     -329.731669        0.960095
LBFGS:   14 17:33:17     -329.812489        1.100032
LBFGS:   15 17:33:17     -329.892535        0.743805
LBFGS:   16 17:33:17     -329.941899        0.452862
LBFGS:   17 17:33:17     -329.968775        0.470555
LBFGS:   18 17:33:17     -329.997084        0.400873
LBFGS:   19 17:33:18     -330.011046        0.946127
LBFGS:   20 17:33:18     -330.021540        0.594087
       Step     Time          Energy          fmax
LBFGS:    0 17:33:18     -329.256671        2.819494
LBFGS:    1 17:33:18     -329.460396        1.434213
LBFGS:    2 17:33:18     -329.577992        0.942200
LBFGS:    3 17:33:19     -329.612793        0.876082
LBFGS:    4 17:33:19     -329.669688        0.456103
LBFGS:    5 17:33:19     -329.683716        0.335050
LBFGS:    6 17:33:19     -329.692038        0.361908
LBFGS:    7 17:33:19     -329.702550        0.349900
LBFGS:    8 17:33:20     -329.719109        0.538261
LBFGS:    9 17:33:20     -329.736918        0.499416
LBFGS:   10 17:33:20     -329.751357        0.440198
LBFGS:   11 17:33:20     -329.768105        0.522355
LBFGS:   12 17:33:20     -329.793051        0.593033
LBFGS:   13 17:33:21     -329.825970        0.699365
LBFGS:   14 17:33:21     -329.863434        0.737331
LBFGS:   15 17:33:21     -329.897257        0.451798
LBFGS:   16 17:33:21     -329.919179        0.308377
LBFGS:   17 17:33:21     -329.939782        0.458434
LBFGS:   18 17:33:21     -329.970376        0.587724
LBFGS:   19 17:33:22     -329.996237        0.462157
LBFGS:   20 17:33:22     -330.011401        0.347201
       Step     Time          Energy          fmax
LBFGS:    0 17:33:22     -329.205531        2.770491
LBFGS:    1 17:33:22     -329.425767        1.349019
LBFGS:    2 17:33:22     -329.544642        0.934502
LBFGS:    3 17:33:23     -329.576281        0.841546
LBFGS:    4 17:33:23     -329.634009        0.618382
LBFGS:    5 17:33:23     -329.649128        0.403441
LBFGS:    6 17:33:23     -329.658314        0.343086
LBFGS:    7 17:33:23     -329.670214        0.412184
LBFGS:    8 17:33:24     -329.686524        0.494460
LBFGS:    9 17:33:24     -329.702441        0.360464
LBFGS:   10 17:33:24     -329.715123        0.422107
LBFGS:   11 17:33:24     -329.731495        0.524073
LBFGS:   12 17:33:24     -329.758103        0.593438
LBFGS:   13 17:33:24     -329.797141        0.846521
LBFGS:   14 17:33:25     -329.845608        0.868018
LBFGS:   15 17:33:25     -329.893464        0.532908
LBFGS:   16 17:33:25     -329.922980        0.296859
LBFGS:   17 17:33:25     -329.944403        0.413119
LBFGS:   18 17:33:25     -329.975661        0.534549
LBFGS:   19 17:33:26     -330.004651        0.487834
LBFGS:   20 17:33:26     -330.024428        0.446997
       Step     Time          Energy          fmax
LBFGS:    0 17:33:26     -329.211251        2.539021
LBFGS:    1 17:33:26     -329.424618        1.304846
LBFGS:    2 17:33:26     -329.546055        0.967949
LBFGS:    3 17:33:27     -329.582858        0.843349
LBFGS:    4 17:33:27     -329.649552        0.715599
LBFGS:    5 17:33:27     -329.668452        0.470626
LBFGS:    6 17:33:27     -329.680205        0.335373
LBFGS:    7 17:33:27     -329.694853        0.424163
LBFGS:    8 17:33:28     -329.717108        0.593455
LBFGS:    9 17:33:28     -329.741135        0.510348
LBFGS:   10 17:33:28     -329.759749        0.552982
LBFGS:   11 17:33:28     -329.783658        0.671055
LBFGS:   12 17:33:28     -329.818903        0.717923
LBFGS:   13 17:33:28     -329.866837        0.852079
LBFGS:   14 17:33:29     -329.926032        0.900696
LBFGS:   15 17:33:29     -329.983862        0.579111
LBFGS:   16 17:33:29     -330.014617        0.273380
LBFGS:   17 17:33:29     -330.030875        0.295822
LBFGS:   18 17:33:29     -330.050549        0.346914
LBFGS:   19 17:33:30     -330.073626        0.689669
LBFGS:   20 17:33:30     -330.085417        0.527675
       Step     Time          Energy          fmax
LBFGS:    0 17:33:30     -329.135083        2.582890
LBFGS:    1 17:33:30     -329.367692        1.265373
LBFGS:    2 17:33:30     -329.494570        1.086838
LBFGS:    3 17:33:31     -329.540070        0.986836
LBFGS:    4 17:33:31     -329.625920        0.962455
LBFGS:    5 17:33:31     -329.667468        0.662331
LBFGS:    6 17:33:31     -329.689782        0.509117
LBFGS:    7 17:33:31     -329.717722        0.575097
LBFGS:    8 17:33:32     -329.760651        0.709057
LBFGS:    9 17:33:32     -329.811249        0.742618
LBFGS:   10 17:33:32     -329.849528        0.627465
LBFGS:   11 17:33:32     -329.893946        0.795321
LBFGS:   12 17:33:32     -329.935422        0.857980
LBFGS:   13 17:33:32     -329.992878        0.844106
LBFGS:   14 17:33:33     -330.053805        0.867202
LBFGS:   15 17:33:33     -330.108351        0.604906
LBFGS:   16 17:33:33     -330.132096        0.442450
LBFGS:   17 17:33:33     -330.135989        0.512795
LBFGS:   18 17:33:33     -330.148461        0.281752
LBFGS:   19 17:33:34     -330.156220        0.200609
LBFGS:   20 17:33:34     -330.171423        0.247177
       Step     Time          Energy          fmax
LBFGS:    0 17:33:34     -328.733918        3.200607
LBFGS:    1 17:33:34     -328.991669        1.490291
LBFGS:    2 17:33:34     -329.154751        1.069567
LBFGS:    3 17:33:35     -329.214297        1.158717
LBFGS:    4 17:33:35     -329.306180        0.880134
LBFGS:    5 17:33:35     -329.354773        0.521385
LBFGS:    6 17:33:35     -329.373812        0.406389
LBFGS:    7 17:33:35     -329.392222        0.423462
LBFGS:    8 17:33:36     -329.424124        0.793776
LBFGS:    9 17:33:36     -329.471215        0.983821
LBFGS:   10 17:33:36     -329.517487        0.720427
LBFGS:   11 17:33:36     -329.554770        0.679030
LBFGS:   12 17:33:36     -329.605511        0.670584
LBFGS:   13 17:33:36     -329.668801        1.013445
LBFGS:   14 17:33:37     -329.743611        1.208171
LBFGS:   15 17:33:37     -329.825675        1.019837
LBFGS:   16 17:33:37     -329.894032        0.502798
LBFGS:   17 17:33:37     -329.929637        0.549666
LBFGS:   18 17:33:37     -329.969443        0.775088
LBFGS:   19 17:33:38     -330.012419        0.637161
LBFGS:   20 17:33:38     -330.041651        0.637440
       Step     Time          Energy          fmax
LBFGS:    0 17:33:38     -328.812855        3.139528
LBFGS:    1 17:33:38     -329.104132        1.659777
LBFGS:    2 17:33:38     -329.261303        1.063174
LBFGS:    3 17:33:39     -329.315398        0.941131
LBFGS:    4 17:33:39     -329.401930        0.762318
LBFGS:    5 17:33:39     -329.432639        0.585125
LBFGS:    6 17:33:39     -329.447836        0.387235
LBFGS:    7 17:33:39     -329.464146        0.482870
LBFGS:    8 17:33:40     -329.488938        0.753914
LBFGS:    9 17:33:40     -329.530215        0.830453
LBFGS:   10 17:33:40     -329.567833        0.643475
LBFGS:   11 17:33:40     -329.601151        0.690318
LBFGS:   12 17:33:40     -329.642041        0.614276
LBFGS:   13 17:33:40     -329.693682        0.974765
LBFGS:   14 17:33:41     -329.754918        1.237428
LBFGS:   15 17:33:41     -329.820445        1.103546
LBFGS:   16 17:33:41     -329.870165        0.439189
LBFGS:   17 17:33:41     -329.893597        0.480292
LBFGS:   18 17:33:41     -329.922288        0.646258
LBFGS:   19 17:33:42     -329.961442        0.807286
LBFGS:   20 17:33:42     -329.985346        0.502170
       Step     Time          Energy          fmax
LBFGS:    0 17:33:42     -329.314454        2.736768
LBFGS:    1 17:33:42     -329.518342        1.399365
LBFGS:    2 17:33:42     -329.630576        0.889341
LBFGS:    3 17:33:43     -329.660504        0.798795
LBFGS:    4 17:33:43     -329.712319        0.471955
LBFGS:    5 17:33:43     -329.722418        0.285311
LBFGS:    6 17:33:43     -329.729035        0.291334
LBFGS:    7 17:33:43     -329.737362        0.353060
LBFGS:    8 17:33:44     -329.748868        0.425698
LBFGS:    9 17:33:44     -329.759112        0.313418
LBFGS:   10 17:33:44     -329.767609        0.363719
LBFGS:   11 17:33:44     -329.779276        0.441882
LBFGS:   12 17:33:44     -329.798649        0.552540
LBFGS:   13 17:33:44     -329.826348        0.683739
LBFGS:   14 17:33:45     -329.857174        0.620640
LBFGS:   15 17:33:45     -329.881232        0.312601
LBFGS:   16 17:33:45     -329.894887        0.283810
LBFGS:   17 17:33:45     -329.911233        0.489720
LBFGS:   18 17:33:45     -329.941626        0.716197
LBFGS:   19 17:33:46     -329.974209        0.678694
LBFGS:   20 17:33:46     -329.992064        0.306152
       Step     Time          Energy          fmax
LBFGS:    0 17:33:46     -329.228392        2.918155
LBFGS:    1 17:33:46     -329.437794        1.484230
LBFGS:    2 17:33:46     -329.555563        0.932665
LBFGS:    3 17:33:47     -329.590764        0.872331
LBFGS:    4 17:33:47     -329.650153        0.486991
LBFGS:    5 17:33:47     -329.665328        0.335098
LBFGS:    6 17:33:47     -329.674773        0.327715
LBFGS:    7 17:33:47     -329.686377        0.376675
LBFGS:    8 17:33:48     -329.703894        0.557299
LBFGS:    9 17:33:48     -329.722815        0.502428
LBFGS:   10 17:33:48     -329.738261        0.468114
LBFGS:   11 17:33:48     -329.756300        0.528958
LBFGS:   12 17:33:48     -329.783667        0.643033
LBFGS:   13 17:33:49     -329.821839        0.804338
LBFGS:   14 17:33:49     -329.866274        0.805008
LBFGS:   15 17:33:49     -329.906334        0.506337
LBFGS:   16 17:33:49     -329.928647        0.355121
LBFGS:   17 17:33:49     -329.945214        0.405214
LBFGS:   18 17:33:49     -329.975028        0.566486
LBFGS:   19 17:33:50     -330.004468        0.509962
LBFGS:   20 17:33:50     -330.020981        0.303745
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.171423483073, 'forces': [[0.0,...
1 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0854173185222, 'forces': [[0.0...
2 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.02442793863946, 'forces': [[0....
3 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0215402128093, 'forces': [[0.0...
4 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0209813596599, 'forces': [[0.0...
5 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0114007474773, 'forces': [[0.0...
6 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.99206404703784, 'forces': [[0....
7 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.9853463651531, 'forces': [[0.0...
8 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.9781404020183, 'forces': [[0.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}/")