Observed since 20 Oct, 19:54 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Adsorption Based on ASE.
A Python package for simulating molecular adsorption on clusters or surfaces, built on top of ASE (Atomic Simulation Environment).
The adsorption package provides tools for placing and optimizing adsorbates (molecules or atoms) on surface or cluster substrates. It automates the process of:
Multiple Adsorption Strategies:
RawAdsorption: Places adsorbates based on geometric site analysis (top, bridge, hollow sites)DirectAdsorption: Uses Fibonacci lattice sampling for comprehensive orientation explorationDirectAdsorptionAD: Extends DirectAdsorption with NequIP-based torch autodiff optimization for GPU-accelerated relaxationFlexible Adsorbate Input:
Atoms objects"O", "C")"H2O", "CO")"C=C-C-C-C-C")Two-Stage Optimization:
Transition State Search:
call_dimer) for saddle point searchescall_neb) for minimum energy path searchesHigh-Throughput Screening:
Helper interface for iterating over both raw and direct adsorption pathspip install adsorption
Or using pixi:
pixi install
from ase.cluster import Octahedron
from adsorption import RawAdsorption, DirectAdsorption
# Create a copper cluster
cluster = Octahedron("Cu", 10)
# Method 1: RawAdsorption (geometric site-based)
ads = RawAdsorption(calculator=None) # Replace with actual calculator
result, stage = ads(
atoms=cluster,
adsorbate="CO",
core=[303, 334, 464], # FCC hollow site
)
# Method 2: DirectAdsorption (Fibonacci lattice sampling)
ads = DirectAdsorption(calculator=None, nfibonacci=100)
result, stage = ads(
atoms=cluster,
adsorbate="C6H6", # Benzene
core=[454], # Top site
)
from ase.cluster import Octahedron
from adsorption.interfaces import DirectAdsorptionAD
from nequip.ase import NequIPCalculator
cluster = Octahedron("Cu", 10)
calc = NequIPCalculator.from_compiled_model("path/to/model.pth")
ads = DirectAdsorptionAD(calculator=calc, nfibonacci=100)
result, stage = ads(atoms=cluster, adsorbate="CO", core=[454])
from ase.cluster import Octahedron
from adsorption.interfaces import Helper
from ase.calculators.emt import EMT
cluster = Octahedron("Cu", 10)
helper = Helper(
calculator=EMT(),
atoms=cluster,
adsorbate="CO",
core=[454],
use_direct=True,
use_raw=True,
)
# Run raw adsorption path
result = helper(irun=0, outdir="./results")
# Run direct adsorption path (iterates over orientation grids)
for i in range(1, helper.nrun):
result = helper(irun=i, outdir="./results")
from ase.build import fcc100
from adsorption.common.optimize import call_dimer, call_neb
from ase.calculators.emt import EMT
# Create a slab
slab = fcc100("Cu", size=(3, 3, 3), vacuum=10)
# Dimer method for saddle point search
trajectory, converged = call_dimer(
slab, EMT(), displacement=..., max_steps=1000, fmax=0.02
)
# NEB method for minimum energy path
initial = slab.copy()
final = slab.copy()
# ... set up initial and final states ...
trajectory, converged = call_neb(
initial, EMT(), final, nimages=5, climb=True
)
The package provides a CLI tool for running high-throughput adsorption studies:
adsorption-tune -cn config.yaml
Example configuration (config.yaml):
output: ./outputs
calculator:
_target_: ase.calculators.emt.EMT
adsorption:
nfibonacci: 100
max_steps_for_first_stage: 100
max_steps_for_second_stage: 100
max_force: 0.05
system:
atoms:
_target_: ase.build.fcc111
symbol: Cu
size: [10, 10, 5]
vacuum: 15
core: [454]
gas: C6H6
src/adsorption/
├── common/
│ ├── __init__.py # Exports AdsorptionABC, Point, Vector, Site
│ ├── _interface.py # Abstract base class (AdsorptionABC)
│ ├── _dataclass.py # Data structures (Point, Vector, Site)
│ └── optimize.py # optimize(), call_dimer(), call_neb()
├── interfaces/
│ ├── __init__.py # Exports RawAdsorption, DirectAdsorption, DirectAdsorptionAD
│ ├── _raw.py # RawAdsorption implementation
│ ├── _direct.py # DirectAdsorption implementation
│ ├── _directAD.py # DirectAdsorptionAD (NequIP + torch autodiff)
│ └── helper.py # Helper class + plot() visualization
└── runner/
├── _cli.py # Hydra-based CLI (adsorption-tune entry point)
├── _cli.yaml # Default Hydra configuration
└── _tune.py # Ray Tune integration
AdsorptionABC (Abstract Base Class)The abstract base class that defines the common interface and optimization workflow:
Two-stage optimization:
Adsorbate parsing: Converts various input types (string, Atom, Atoms, Gas) to ASE Atoms
RawAdsorptionPlaces adsorbates based on geometric analysis of adsorption sites:
Parameters:
adsorbate_index: Index of anchoring atom in adsorbate (or "com" for center of mass)nbr1hop: First-neighbor shell indices (auto-detected if not provided)core: Core atom indices defining the adsorption siteDirectAdsorptionUses Fibonacci lattice sampling for comprehensive orientation exploration:
Parameters:
nfibonacci: Number of Fibonacci lattice points (default: 1000)grid_core: Custom grid for substrate orientationsgrid_ads: Custom grid for adsorbate orientationsdistance: Adsorbate-substrate distanceDirectAdsorptionADExtends DirectAdsorption with NequIP-based torch autodiff optimization:
NequIPCalculator instancetorch.optim.LBFGS for GPU-accelerated relaxationHelperUnified interface that wraps both RawAdsorption and DirectAdsorption:
irun=0: Runs the raw adsorption pathirun>=1: Runs the direct adsorption path (iterates over orientation x distance grids)All defined in common/_dataclass.py as Pydantic models:
Point: 3D point with arithmetic operationsVector: 3D vector with length and normalize propertiesSite: Adsorption site with neighbor, core, computed center and directioncommon/optimize.py provides:
optimize(atoms, calc, method, max_steps, fmax): General ASE structure optimization with trajectory recording. Returns (trajectory, converged).call_dimer(atoms, calc, displacement, mask, max_steps, fmax): Dimer method for transition state search. Returns (trajectory, converged).call_neb(atoms, calc, final_atoms, nimages, climb, ...): DyNEB method for minimum energy path search. Returns (trajectory, converged).from ase.build import fcc111
from adsorption import DirectAdsorption
from ase.calculators.emt import EMT
# Create Cu(111) surface
surface = fcc111("Cu", size=(10, 10, 5), vacuum=15, orthogonal=True)
# Initialize adsorption calculator
ads = DirectAdsorption(
calculator=EMT(),
nfibonacci=100,
max_steps_for_first_stage=100,
max_steps_for_second_stage=100,
)
# Place benzene on surface
result, stage = ads(
atoms=surface,
adsorbate="C6H6",
core=[454], # Surface site index
)
from ase.cluster import Octahedron
from adsorption import RawAdsorption
# Create octahedral Cu cluster
cluster = Octahedron("Cu", 10)
# Place CO on FCC hollow site
ads = RawAdsorption(calculator=None)
result, stage = ads(
atoms=cluster,
adsorbate="CO",
core=[303, 334, 464], # FCC hollow site
adsorbate_index=0, # Anchor on carbon atom
)
The tune_adsorption function enables parallel exploration of multiple adsorption configurations:
from pathlib import Path
from adsorption.runner._tune import tune_adsorption
from ase.build import fcc111
surface = fcc111("Cu", size=(10, 10, 5), vacuum=15)
results = tune_adsorption(
cfg=config, # DictConfig with calculator and adsorption settings
atoms=surface,
adsorbate="C6H6",
core=[454],
nsamples=100, # Number of random samples
output=Path("./results"),
)
Results are saved as:
.xyz files with energy and optimization stage in filename.png visualization files with multiple viewing anglesDirectAdsorptionADpixi run test
# or
pytest -s -vv
The project uses:
GPL-3.0-or-later
LiuGaoyong (liugaoyong_88@163.com)
pypistats · 63 observations shown. Missing days are unknown. Source category: overall: without mirrors.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-20 – 2026-10-20 | 4 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-19 – 2026-10-19 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-18 – 2026-10-18 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-17 – 2026-10-17 | 3 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-16 – 2026-10-16 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-15 – 2026-10-15 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-14 – 2026-10-14 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-13 – 2026-10-13 | 8 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-12 – 2026-10-12 | 4 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-11 – 2026-10-11 | 17 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-10 – 2026-10-10 | 5 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-09 – 2026-10-09 | 3 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-08 – 2026-10-08 | 17 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-07 – 2026-10-07 | 3 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-06 – 2026-10-06 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-04 – 2026-10-04 | 7 | 2026-10-21T13:45:37.2708459Z |
| 2026-10-02 – 2026-10-02 | 6 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-30 – 2026-09-30 | 3 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-29 – 2026-09-29 | 4 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-28 – 2026-09-28 | 5 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-27 – 2026-09-27 | 7 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-26 – 2026-09-26 | 5 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-25 – 2026-09-25 | 8 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-24 – 2026-09-24 | 28 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-23 – 2026-09-23 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-22 – 2026-09-22 | 3 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-21 – 2026-09-21 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-19 – 2026-09-19 | 18 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-18 – 2026-09-18 | 3 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-15 – 2026-09-15 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-13 – 2026-09-13 | 13 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-12 – 2026-09-12 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-10 – 2026-09-10 | 8 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-09 – 2026-09-09 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-08 – 2026-09-08 | 4 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-07 – 2026-09-07 | 21 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-05 – 2026-09-05 | 3 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-04 – 2026-09-04 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-03 – 2026-09-03 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-09-01 – 2026-09-01 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-31 – 2026-08-31 | 3 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-28 – 2026-08-28 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-25 – 2026-08-25 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-24 – 2026-08-24 | 15 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-23 – 2026-08-23 | 4 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-21 – 2026-08-21 | 5 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-20 – 2026-08-20 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-18 – 2026-08-18 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-17 – 2026-08-17 | 3 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-14 – 2026-08-14 | 4 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-13 – 2026-08-13 | 13 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-11 – 2026-08-11 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-09 – 2026-08-09 | 8 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-05 – 2026-08-05 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-04 – 2026-08-04 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-03 – 2026-08-03 | 6 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-02 – 2026-08-02 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-08-01 – 2026-08-01 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-07-31 – 2026-07-31 | 2 | 2026-10-21T13:45:37.2708459Z |
| 2026-07-29 – 2026-07-29 | 4 | 2026-10-21T13:45:37.2708459Z |
| 2026-07-27 – 2026-07-27 | 1 | 2026-10-21T13:45:37.2708459Z |
| 2026-07-24 – 2026-07-24 | 7 | 2026-10-21T13:45:37.2708459Z |
| 2026-07-23 – 2026-07-23 | 2 | 2026-10-21T13:45:37.2708459Z |
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.2 | 11 Jun 2026 | 5 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 19:54 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:2a058f0e37d576c892a45dbe62f7b498f847d13777d1277d8c86fcc977b8d2a8