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 00:41:40     -300.219297        0.047121
LBFGS:    1 00:41:40     -300.219795        0.045100
LBFGS:    2 00:41:40     -300.225582        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 00:41:41     -329.009724        2.969514
LBFGS:    1 00:41:41     -329.262831        1.461636
LBFGS:    2 00:41:41     -329.394581        0.970977
LBFGS:    3 00:41:41     -329.437783        0.865701
LBFGS:    4 00:41:42     -329.510417        0.710860
LBFGS:    5 00:41:42     -329.535742        0.527391
LBFGS:    6 00:41:42     -329.547659        0.368415
LBFGS:    7 00:41:42     -329.559615        0.412730
LBFGS:    8 00:41:42     -329.577612        0.612673
LBFGS:    9 00:41:42     -329.603829        0.625862
LBFGS:   10 00:41:43     -329.627175        0.542622
LBFGS:   11 00:41:43     -329.650067        0.598548
LBFGS:   12 00:41:43     -329.681851        0.556408
LBFGS:   13 00:41:43     -329.724471        0.898875
LBFGS:   14 00:41:43     -329.774590        1.075321
LBFGS:   15 00:41:44     -329.824788        0.864956
LBFGS:   16 00:41:44     -329.859664        0.402824
LBFGS:   17 00:41:44     -329.880385        0.496848
LBFGS:   18 00:41:44     -329.913308        0.741555
LBFGS:   19 00:41:44     -329.952426        0.843885
LBFGS:   20 00:41:44     -329.978138        0.517967
       Step     Time          Energy          fmax
LBFGS:    0 00:41:45     -328.863089        3.004485
LBFGS:    1 00:41:45     -329.128964        1.449172
LBFGS:    2 00:41:45     -329.297511        1.136809
LBFGS:    3 00:41:45     -329.349669        1.035450
LBFGS:    4 00:41:45     -329.442961        0.754515
LBFGS:    5 00:41:46     -329.470618        0.464068
LBFGS:    6 00:41:46     -329.485611        0.474616
LBFGS:    7 00:41:46     -329.507023        0.504682
LBFGS:    8 00:41:46     -329.534337        0.710157
LBFGS:    9 00:41:46     -329.564232        0.611191
LBFGS:   10 00:41:47     -329.587128        0.594175
LBFGS:   11 00:41:47     -329.618067        0.757966
LBFGS:   12 00:41:47     -329.666018        0.844176
LBFGS:   13 00:41:47     -329.731675        0.960133
LBFGS:   14 00:41:47     -329.812493        1.100091
LBFGS:   15 00:41:47     -329.892535        0.743790
LBFGS:   16 00:41:48     -329.941905        0.452808
LBFGS:   17 00:41:48     -329.968772        0.470710
LBFGS:   18 00:41:48     -329.997098        0.400633
LBFGS:   19 00:41:48     -330.011120        0.943632
LBFGS:   20 00:41:48     -330.021605        0.591666
       Step     Time          Energy          fmax
LBFGS:    0 00:41:49     -329.256671        2.819493
LBFGS:    1 00:41:49     -329.460396        1.434213
LBFGS:    2 00:41:49     -329.577992        0.942200
LBFGS:    3 00:41:49     -329.612790        0.876082
LBFGS:    4 00:41:49     -329.669686        0.456102
LBFGS:    5 00:41:50     -329.683716        0.335050
LBFGS:    6 00:41:50     -329.692040        0.361908
LBFGS:    7 00:41:50     -329.702550        0.349900
LBFGS:    8 00:41:50     -329.719109        0.538265
LBFGS:    9 00:41:50     -329.736916        0.499415
LBFGS:   10 00:41:50     -329.751360        0.440198
LBFGS:   11 00:41:51     -329.768107        0.522356
LBFGS:   12 00:41:51     -329.793053        0.593059
LBFGS:   13 00:41:51     -329.825976        0.699330
LBFGS:   14 00:41:51     -329.863436        0.737318
LBFGS:   15 00:41:51     -329.897252        0.451804
LBFGS:   16 00:41:52     -329.919179        0.308367
LBFGS:   17 00:41:52     -329.939787        0.458371
LBFGS:   18 00:41:52     -329.970377        0.587803
LBFGS:   19 00:41:52     -329.996243        0.462000
LBFGS:   20 00:41:52     -330.011393        0.346936
       Step     Time          Energy          fmax
LBFGS:    0 00:41:52     -329.205535        2.770491
LBFGS:    1 00:41:53     -329.425767        1.349019
LBFGS:    2 00:41:53     -329.544642        0.934502
LBFGS:    3 00:41:53     -329.576281        0.841546
LBFGS:    4 00:41:53     -329.634013        0.618370
LBFGS:    5 00:41:54     -329.649132        0.403441
LBFGS:    6 00:41:54     -329.658312        0.343091
LBFGS:    7 00:41:54     -329.670214        0.412214
LBFGS:    8 00:41:54     -329.686524        0.494442
LBFGS:    9 00:41:54     -329.702441        0.360468
LBFGS:   10 00:41:55     -329.715113        0.422153
LBFGS:   11 00:41:55     -329.731492        0.524001
LBFGS:   12 00:41:55     -329.758095        0.593483
LBFGS:   13 00:41:55     -329.797143        0.846543
LBFGS:   14 00:41:55     -329.845612        0.867968
LBFGS:   15 00:41:55     -329.893469        0.532875
LBFGS:   16 00:41:56     -329.922974        0.296859
LBFGS:   17 00:41:56     -329.944405        0.413100
LBFGS:   18 00:41:56     -329.975657        0.534607
LBFGS:   19 00:41:56     -330.004653        0.487888
LBFGS:   20 00:41:56     -330.024428        0.446809
       Step     Time          Energy          fmax
LBFGS:    0 00:41:57     -329.211251        2.539020
LBFGS:    1 00:41:57     -329.424620        1.304846
LBFGS:    2 00:41:57     -329.546055        0.967949
LBFGS:    3 00:41:57     -329.582854        0.843348
LBFGS:    4 00:41:57     -329.649554        0.715603
LBFGS:    5 00:41:58     -329.668454        0.470625
LBFGS:    6 00:41:58     -329.680209        0.335373
LBFGS:    7 00:41:58     -329.694855        0.424166
LBFGS:    8 00:41:58     -329.717103        0.593449
LBFGS:    9 00:41:58     -329.741133        0.510327
LBFGS:   10 00:41:58     -329.759741        0.552975
LBFGS:   11 00:41:59     -329.783658        0.671113
LBFGS:   12 00:41:59     -329.818898        0.717894
LBFGS:   13 00:41:59     -329.866839        0.852056
LBFGS:   14 00:41:59     -329.926032        0.900713
LBFGS:   15 00:41:59     -329.983861        0.579153
LBFGS:   16 00:42:00     -330.014618        0.273312
LBFGS:   17 00:42:00     -330.030873        0.295836
LBFGS:   18 00:42:00     -330.050547        0.347012
LBFGS:   19 00:42:00     -330.073626        0.689412
LBFGS:   20 00:42:00     -330.085440        0.526934
       Step     Time          Energy          fmax
LBFGS:    0 00:42:01     -329.135081        2.582889
LBFGS:    1 00:42:01     -329.367690        1.265373
LBFGS:    2 00:42:01     -329.494574        1.086839
LBFGS:    3 00:42:01     -329.540066        0.986836
LBFGS:    4 00:42:01     -329.625918        0.962460
LBFGS:    5 00:42:01     -329.667468        0.662332
LBFGS:    6 00:42:02     -329.689784        0.509116
LBFGS:    7 00:42:02     -329.717722        0.575098
LBFGS:    8 00:42:02     -329.760659        0.709041
LBFGS:    9 00:42:02     -329.811249        0.742618
LBFGS:   10 00:42:02     -329.849524        0.627462
LBFGS:   11 00:42:03     -329.893944        0.795315
LBFGS:   12 00:42:03     -329.935423        0.857979
LBFGS:   13 00:42:03     -329.992878        0.844079
LBFGS:   14 00:42:03     -330.053809        0.867177
LBFGS:   15 00:42:03     -330.108349        0.604918
LBFGS:   16 00:42:04     -330.132094        0.442633
LBFGS:   17 00:42:04     -330.135981        0.513138
LBFGS:   18 00:42:04     -330.148461        0.281719
LBFGS:   19 00:42:04     -330.156214        0.200585
LBFGS:   20 00:42:04     -330.171406        0.247330
       Step     Time          Energy          fmax
LBFGS:    0 00:42:04     -328.733914        3.200604
LBFGS:    1 00:42:05     -328.991669        1.490292
LBFGS:    2 00:42:05     -329.154746        1.069564
LBFGS:    3 00:42:05     -329.214303        1.158717
LBFGS:    4 00:42:05     -329.306187        0.880134
LBFGS:    5 00:42:05     -329.354773        0.521386
LBFGS:    6 00:42:06     -329.373820        0.406388
LBFGS:    7 00:42:06     -329.392216        0.423463
LBFGS:    8 00:42:06     -329.424124        0.793743
LBFGS:    9 00:42:06     -329.471213        0.983833
LBFGS:   10 00:42:06     -329.517483        0.720401
LBFGS:   11 00:42:07     -329.554766        0.678967
LBFGS:   12 00:42:07     -329.605511        0.670667
LBFGS:   13 00:42:07     -329.668793        1.013352
LBFGS:   14 00:42:07     -329.743609        1.208143
LBFGS:   15 00:42:07     -329.825671        1.019871
LBFGS:   16 00:42:07     -329.894036        0.502789
LBFGS:   17 00:42:08     -329.929631        0.549687
LBFGS:   18 00:42:08     -329.969449        0.775049
LBFGS:   19 00:42:08     -330.012415        0.637181
LBFGS:   20 00:42:08     -330.041649        0.637534
       Step     Time          Energy          fmax
LBFGS:    0 00:42:08     -328.812855        3.139527
LBFGS:    1 00:42:09     -329.104132        1.659777
LBFGS:    2 00:42:09     -329.261303        1.063174
LBFGS:    3 00:42:09     -329.315396        0.941131
LBFGS:    4 00:42:09     -329.401928        0.762322
LBFGS:    5 00:42:09     -329.432641        0.585125
LBFGS:    6 00:42:10     -329.447836        0.387234
LBFGS:    7 00:42:10     -329.464148        0.482866
LBFGS:    8 00:42:10     -329.488934        0.753850
LBFGS:    9 00:42:10     -329.530211        0.830548
LBFGS:   10 00:42:10     -329.567839        0.643508
LBFGS:   11 00:42:11     -329.601143        0.690267
LBFGS:   12 00:42:11     -329.642043        0.614270
LBFGS:   13 00:42:11     -329.693688        0.974813
LBFGS:   14 00:42:11     -329.754914        1.237395
LBFGS:   15 00:42:11     -329.820450        1.103498
LBFGS:   16 00:42:11     -329.870165        0.439137
LBFGS:   17 00:42:12     -329.893593        0.480319
LBFGS:   18 00:42:12     -329.922291        0.646344
LBFGS:   19 00:42:12     -329.961443        0.807266
LBFGS:   20 00:42:12     -329.985346        0.502186
       Step     Time          Energy          fmax
LBFGS:    0 00:42:12     -329.314454        2.736768
LBFGS:    1 00:42:13     -329.518338        1.399364
LBFGS:    2 00:42:13     -329.630580        0.889341
LBFGS:    3 00:42:13     -329.660506        0.798794
LBFGS:    4 00:42:13     -329.712319        0.471959
LBFGS:    5 00:42:13     -329.722420        0.285311
LBFGS:    6 00:42:14     -329.729035        0.291327
LBFGS:    7 00:42:14     -329.737355        0.353116
LBFGS:    8 00:42:14     -329.748868        0.425699
LBFGS:    9 00:42:14     -329.759108        0.313407
LBFGS:   10 00:42:14     -329.767613        0.363659
LBFGS:   11 00:42:14     -329.779276        0.441810
LBFGS:   12 00:42:15     -329.798657        0.552598
LBFGS:   13 00:42:15     -329.826342        0.683677
LBFGS:   14 00:42:15     -329.857169        0.620637
LBFGS:   15 00:42:15     -329.881224        0.312586
LBFGS:   16 00:42:15     -329.894888        0.283830
LBFGS:   17 00:42:16     -329.911231        0.489778
LBFGS:   18 00:42:16     -329.941622        0.716203
LBFGS:   19 00:42:16     -329.974207        0.678630
LBFGS:   20 00:42:16     -329.992068        0.306236
       Step     Time          Energy          fmax
LBFGS:    0 00:42:16     -329.228392        2.918154
LBFGS:    1 00:42:16     -329.437796        1.484230
LBFGS:    2 00:42:17     -329.555562        0.932666
LBFGS:    3 00:42:17     -329.590764        0.872369
LBFGS:    4 00:42:17     -329.650147        0.487018
LBFGS:    5 00:42:17     -329.665322        0.335142
LBFGS:    6 00:42:17     -329.674779        0.327685
LBFGS:    7 00:42:18     -329.686381        0.376646
LBFGS:    8 00:42:18     -329.703894        0.557249
LBFGS:    9 00:42:18     -329.722809        0.502487
LBFGS:   10 00:42:18     -329.738261        0.468223
LBFGS:   11 00:42:18     -329.756299        0.528911
LBFGS:   12 00:42:19     -329.783665        0.643210
LBFGS:   13 00:42:19     -329.821835        0.804381
LBFGS:   14 00:42:19     -329.866280        0.804979
LBFGS:   15 00:42:19     -329.906336        0.506411
LBFGS:   16 00:42:19     -329.928639        0.355102
LBFGS:   17 00:42:20     -329.945206        0.405238
LBFGS:   18 00:42:20     -329.975033        0.566563
LBFGS:   19 00:42:20     -330.004466        0.509970
LBFGS:   20 00:42:20     -330.020985        0.303906
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.1714063169353, 'forces': [[0.0...
1 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0854402067058, 'forces': [[0.0...
2 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0244279386394, 'forces': [[0.0...
3 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.02160506266284, 'forces': [[0....
4 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0209851743572, 'forces': [[0.0...
5 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.01139311808276, 'forces': [[0....
6 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.9920678617351, 'forces': [[0.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.9781384946697, '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}/")