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 18:52:14     -300.219297        0.047121
LBFGS:    1 18:52:14     -300.219791        0.045100
LBFGS:    2 18:52:14     -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 18:52:15     -329.009720        2.969513
LBFGS:    1 18:52:15     -329.262831        1.461636
LBFGS:    2 18:52:15     -329.394583        0.970980
LBFGS:    3 18:52:16     -329.437779        0.865683
LBFGS:    4 18:52:16     -329.510418        0.710859
LBFGS:    5 18:52:16     -329.535744        0.527409
LBFGS:    6 18:52:16     -329.547667        0.368460
LBFGS:    7 18:52:16     -329.559611        0.412818
LBFGS:    8 18:52:16     -329.577612        0.612530
LBFGS:    9 18:52:17     -329.603842        0.625800
LBFGS:   10 18:52:17     -329.627181        0.542659
LBFGS:   11 18:52:17     -329.650073        0.598625
LBFGS:   12 18:52:17     -329.681866        0.556472
LBFGS:   13 18:52:17     -329.724480        0.899026
LBFGS:   14 18:52:18     -329.774582        1.075264
LBFGS:   15 18:52:18     -329.824795        0.864866
LBFGS:   16 18:52:18     -329.859658        0.402802
LBFGS:   17 18:52:18     -329.880379        0.496913
LBFGS:   18 18:52:18     -329.913312        0.741679
LBFGS:   19 18:52:18     -329.952429        0.843960
LBFGS:   20 18:52:19     -329.978152        0.517999
       Step     Time          Energy          fmax
LBFGS:    0 18:52:19     -328.863087        3.004486
LBFGS:    1 18:52:19     -329.128964        1.449172
LBFGS:    2 18:52:19     -329.297530        1.136905
LBFGS:    3 18:52:19     -329.349667        1.035495
LBFGS:    4 18:52:20     -329.442998        0.754109
LBFGS:    5 18:52:20     -329.470618        0.464096
LBFGS:    6 18:52:20     -329.485613        0.474611
LBFGS:    7 18:52:20     -329.507031        0.504844
LBFGS:    8 18:52:20     -329.534361        0.710315
LBFGS:    9 18:52:21     -329.564246        0.611080
LBFGS:   10 18:52:21     -329.587153        0.594262
LBFGS:   11 18:52:21     -329.618100        0.757996
LBFGS:   12 18:52:21     -329.666060        0.844082
LBFGS:   13 18:52:21     -329.731726        0.960199
LBFGS:   14 18:52:21     -329.812535        1.099765
LBFGS:   15 18:52:22     -329.892554        0.743130
LBFGS:   16 18:52:22     -329.941865        0.452561
LBFGS:   17 18:52:22     -329.968739        0.471360
LBFGS:   18 18:52:22     -329.997141        0.400184
LBFGS:   19 18:52:22     -330.011368        0.935301
LBFGS:   20 18:52:23     -330.021752        0.585470
       Step     Time          Energy          fmax
LBFGS:    0 18:52:23     -329.256669        2.819492
LBFGS:    1 18:52:23     -329.460398        1.434213
LBFGS:    2 18:52:23     -329.577994        0.942242
LBFGS:    3 18:52:23     -329.612790        0.876027
LBFGS:    4 18:52:24     -329.669688        0.456018
LBFGS:    5 18:52:24     -329.683718        0.335053
LBFGS:    6 18:52:24     -329.692030        0.361899
LBFGS:    7 18:52:24     -329.702544        0.349866
LBFGS:    8 18:52:24     -329.719119        0.538391
LBFGS:    9 18:52:24     -329.736922        0.499446
LBFGS:   10 18:52:25     -329.751368        0.440245
LBFGS:   11 18:52:25     -329.768120        0.522297
LBFGS:   12 18:52:25     -329.793061        0.593009
LBFGS:   13 18:52:25     -329.825993        0.699370
LBFGS:   14 18:52:25     -329.863446        0.737231
LBFGS:   15 18:52:26     -329.897254        0.451577
LBFGS:   16 18:52:26     -329.919169        0.308347
LBFGS:   17 18:52:26     -329.939778        0.458402
LBFGS:   18 18:52:26     -329.970376        0.587934
LBFGS:   19 18:52:26     -329.996241        0.462136
LBFGS:   20 18:52:27     -330.011393        0.346909
       Step     Time          Energy          fmax
LBFGS:    0 18:52:27     -329.205529        2.770491
LBFGS:    1 18:52:27     -329.425761        1.349018
LBFGS:    2 18:52:27     -329.544642        0.934491
LBFGS:    3 18:52:27     -329.576281        0.841547
LBFGS:    4 18:52:28     -329.634003        0.618358
LBFGS:    5 18:52:28     -329.649132        0.403423
LBFGS:    6 18:52:28     -329.658309        0.343103
LBFGS:    7 18:52:28     -329.670216        0.412139
LBFGS:    8 18:52:28     -329.686518        0.494466
LBFGS:    9 18:52:28     -329.702441        0.360530
LBFGS:   10 18:52:29     -329.715127        0.422161
LBFGS:   11 18:52:29     -329.731497        0.524038
LBFGS:   12 18:52:29     -329.758107        0.593418
LBFGS:   13 18:52:29     -329.797150        0.846414
LBFGS:   14 18:52:29     -329.845616        0.867958
LBFGS:   15 18:52:30     -329.893458        0.532846
LBFGS:   16 18:52:30     -329.922970        0.297064
LBFGS:   17 18:52:30     -329.944394        0.413057
LBFGS:   18 18:52:30     -329.975644        0.534639
LBFGS:   19 18:52:30     -330.004647        0.488172
LBFGS:   20 18:52:31     -330.024411        0.446621
       Step     Time          Energy          fmax
LBFGS:    0 18:52:31     -329.211249        2.539020
LBFGS:    1 18:52:31     -329.424614        1.304845
LBFGS:    2 18:52:31     -329.546065        0.967964
LBFGS:    3 18:52:31     -329.582850        0.843348
LBFGS:    4 18:52:31     -329.649565        0.715534
LBFGS:    5 18:52:32     -329.668446        0.470573
LBFGS:    6 18:52:32     -329.680209        0.335346
LBFGS:    7 18:52:32     -329.694863        0.424289
LBFGS:    8 18:52:32     -329.717116        0.593549
LBFGS:    9 18:52:32     -329.741145        0.510389
LBFGS:   10 18:52:33     -329.759757        0.553053
LBFGS:   11 18:52:33     -329.783667        0.671036
LBFGS:   12 18:52:33     -329.818924        0.717864
LBFGS:   13 18:52:33     -329.866862        0.852156
LBFGS:   14 18:52:33     -329.926051        0.900669
LBFGS:   15 18:52:34     -329.983866        0.579035
LBFGS:   16 18:52:34     -330.014620        0.273191
LBFGS:   17 18:52:34     -330.030871        0.295813
LBFGS:   18 18:52:34     -330.050572        0.346503
LBFGS:   19 18:52:34     -330.073607        0.690798
LBFGS:   20 18:52:34     -330.085286        0.532419
       Step     Time          Energy          fmax
LBFGS:    0 18:52:35     -329.135081        2.582889
LBFGS:    1 18:52:35     -329.367686        1.265373
LBFGS:    2 18:52:35     -329.494574        1.086841
LBFGS:    3 18:52:35     -329.540066        0.986831
LBFGS:    4 18:52:35     -329.625926        0.962404
LBFGS:    5 18:52:36     -329.667471        0.662281
LBFGS:    6 18:52:36     -329.689784        0.509088
LBFGS:    7 18:52:36     -329.717734        0.575101
LBFGS:    8 18:52:36     -329.760651        0.708972
LBFGS:    9 18:52:36     -329.811257        0.742571
LBFGS:   10 18:52:37     -329.849522        0.627483
LBFGS:   11 18:52:37     -329.893956        0.795618
LBFGS:   12 18:52:37     -329.935406        0.857914
LBFGS:   13 18:52:37     -329.992936        0.844206
LBFGS:   14 18:52:37     -330.053814        0.867172
LBFGS:   15 18:52:38     -330.108365        0.605079
LBFGS:   16 18:52:38     -330.132168        0.437224
LBFGS:   17 18:52:38     -330.136241        0.503541
LBFGS:   18 18:52:38     -330.148570        0.281934
LBFGS:   19 18:52:38     -330.156340        0.200706
LBFGS:   20 18:52:38     -330.171769        0.241433
       Step     Time          Energy          fmax
LBFGS:    0 18:52:39     -328.733918        3.200607
LBFGS:    1 18:52:39     -328.991665        1.490291
LBFGS:    2 18:52:39     -329.154738        1.069548
LBFGS:    3 18:52:39     -329.214297        1.158683
LBFGS:    4 18:52:39     -329.306176        0.880184
LBFGS:    5 18:52:40     -329.354771        0.521447
LBFGS:    6 18:52:40     -329.373808        0.406390
LBFGS:    7 18:52:40     -329.392212        0.423459
LBFGS:    8 18:52:40     -329.424124        0.793714
LBFGS:    9 18:52:40     -329.471207        0.983928
LBFGS:   10 18:52:41     -329.517487        0.720514
LBFGS:   11 18:52:41     -329.554766        0.678945
LBFGS:   12 18:52:41     -329.605507        0.670710
LBFGS:   13 18:52:41     -329.668784        1.013304
LBFGS:   14 18:52:41     -329.743598        1.208166
LBFGS:   15 18:52:42     -329.825652        1.019960
LBFGS:   16 18:52:42     -329.894017        0.502908
LBFGS:   17 18:52:42     -329.929631        0.549738
LBFGS:   18 18:52:42     -329.969439        0.775160
LBFGS:   19 18:52:42     -330.012412        0.637234
LBFGS:   20 18:52:42     -330.041630        0.638284
       Step     Time          Energy          fmax
LBFGS:    0 18:52:43     -328.812855        3.139526
LBFGS:    1 18:52:43     -329.104130        1.659777
LBFGS:    2 18:52:43     -329.261296        1.063189
LBFGS:    3 18:52:43     -329.315388        0.941084
LBFGS:    4 18:52:43     -329.401923        0.762254
LBFGS:    5 18:52:44     -329.432643        0.585085
LBFGS:    6 18:52:44     -329.447831        0.387243
LBFGS:    7 18:52:44     -329.464142        0.482830
LBFGS:    8 18:52:44     -329.488940        0.754029
LBFGS:    9 18:52:44     -329.530217        0.830470
LBFGS:   10 18:52:45     -329.567835        0.643465
LBFGS:   11 18:52:45     -329.601153        0.690267
LBFGS:   12 18:52:45     -329.642039        0.614287
LBFGS:   13 18:52:45     -329.693692        0.974750
LBFGS:   14 18:52:45     -329.754918        1.237400
LBFGS:   15 18:52:45     -329.820445        1.103462
LBFGS:   16 18:52:46     -329.870160        0.439190
LBFGS:   17 18:52:46     -329.893588        0.480343
LBFGS:   18 18:52:46     -329.922289        0.646413
LBFGS:   19 18:52:46     -329.961438        0.807344
LBFGS:   20 18:52:46     -329.985348        0.502198
       Step     Time          Energy          fmax
LBFGS:    0 18:52:47     -329.314457        2.736769
LBFGS:    1 18:52:47     -329.518340        1.399365
LBFGS:    2 18:52:47     -329.630580        0.889362
LBFGS:    3 18:52:47     -329.660500        0.798830
LBFGS:    4 18:52:47     -329.712325        0.471946
LBFGS:    5 18:52:48     -329.722420        0.285260
LBFGS:    6 18:52:48     -329.729027        0.291239
LBFGS:    7 18:52:48     -329.737361        0.353118
LBFGS:    8 18:52:48     -329.748873        0.425757
LBFGS:    9 18:52:48     -329.759114        0.313406
LBFGS:   10 18:52:49     -329.767611        0.363705
LBFGS:   11 18:52:49     -329.779278        0.441911
LBFGS:   12 18:52:49     -329.798655        0.552673
LBFGS:   13 18:52:49     -329.826346        0.683732
LBFGS:   14 18:52:49     -329.857182        0.620580
LBFGS:   15 18:52:49     -329.881241        0.312480
LBFGS:   16 18:52:50     -329.894890        0.283784
LBFGS:   17 18:52:50     -329.911229        0.489797
LBFGS:   18 18:52:50     -329.941636        0.716169
LBFGS:   19 18:52:50     -329.974209        0.678489
LBFGS:   20 18:52:50     -329.992060        0.306030
       Step     Time          Energy          fmax
LBFGS:    0 18:52:51     -329.228390        2.918154
LBFGS:    1 18:52:51     -329.437794        1.484229
LBFGS:    2 18:52:51     -329.555565        0.932672
LBFGS:    3 18:52:51     -329.590760        0.872376
LBFGS:    4 18:52:51     -329.650160        0.486894
LBFGS:    5 18:52:52     -329.665326        0.335022
LBFGS:    6 18:52:52     -329.674771        0.327778
LBFGS:    7 18:52:52     -329.686383        0.376768
LBFGS:    8 18:52:52     -329.703900        0.557272
LBFGS:    9 18:52:52     -329.722823        0.502434
LBFGS:   10 18:52:53     -329.738276        0.468222
LBFGS:   11 18:52:53     -329.756323        0.529019
LBFGS:   12 18:52:53     -329.783692        0.643065
LBFGS:   13 18:52:53     -329.821881        0.804376
LBFGS:   14 18:52:53     -329.866307        0.804872
LBFGS:   15 18:52:53     -329.906363        0.506044
LBFGS:   16 18:52:54     -329.928645        0.354980
LBFGS:   17 18:52:54     -329.945229        0.405399
LBFGS:   18 18:52:54     -329.975018        0.566517
LBFGS:   19 18:52:54     -330.004450        0.510573
LBFGS:   20 18:52:54     -330.020989        0.304556
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.1717687131756, 'forces': [[0.0...
1 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0852857114666, 'forces': [[0.0...
2 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0244107725017, 'forces': [[0.0...
3 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.02175192850757, 'forces': [[0....
4 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0209889890545, 'forces': [[0.0...
5 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -330.0113931180828, 'forces': [[0.0...
6 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.99206023234063, 'forces': [[0....
7 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.98534827250177, 'forces': [[0....
8 {'atoms': (Atom('Cu', [np.float64(-1.300046521... (Atom('Cu', [np.float64(-1.3000465215529715), ... {'energy': -329.97815184611017, '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}/")