βš—οΈ NVIDIA ALCHEMI: AI-Powered Chemistry & Materials Simulation at Mahidol#

Author: Snit Sanghlao, Qwen, Claude Created: 2026-07-22 | Last Updated: 2026-07-22

GPU-Accelerated Atomistic Simulation via NVIDIA NIM Microservices#

This guide covers the use of NVIDIA ALCHEMI β€” a collection of GPU-accelerated AI microservices for chemistry and materials science β€” deployed on the Mahidol AI Center Kubernetes cluster. ALCHEMI enables near-quantum chemistry accuracy simulations at a fraction of the compute cost, powered by Machine Learning Interatomic Potentials (MLIPs) running on NVIDIA A100 GPUs.


πŸ“Š Service Specifications#

Feature

BGR (Geometry Relaxation)

BMD (Molecular Dynamics)

NIM Image

nvcr.io/nim/nvidia/alchemi-bgr:1.0.0

nvcr.io/nim/nvidia/alchemi-bmd:1.0.0

Model

MACE-MP-0 (pre-bundled)

MACE-MPA-0 (pre-bundled)

API Endpoint

https://aicenter.mahidol.ac.th/alchemi-bgr/v1/infer

https://aicenter.mahidol.ac.th/alchemi-bmd/v1/infer

Health Check

/alchemi-bgr/v1/health/ready

/alchemi-bmd/v1/health/ready

GPU

2x A100

2x A100

Ensembles

Geometry optimization (FIRE2)

NVE, NVT, NPT

Accuracy

Near-DFT level (~meV/atom error)

Near-DFT level (~meV/atom error)


πŸ”¬ What Is ALCHEMI?#

Traditional computational chemistry faces a trade-off: Density Functional Theory (DFT) is accurate but scales as O(NΒ³) and takes hours per molecule. Classical force fields are fast but lack chemical accuracy. ALCHEMI breaks this barrier using Machine Learning Interatomic Potentials (MLIPs) trained on millions of DFT calculations, delivering:

  • Near-DFT accuracy β€” energy MAE on the order of 10–20 meV/atom vs. quantum chemistry (MACE foundation models)

  • 100x speedup over DFT β€” seconds instead of hours per structure (NVIDIA ALCHEMI)

  • Batched inference β€” process hundreds of molecules simultaneously on GPU

  • No local installation β€” REST API access from any Python environment

The underlying model (MACE-MP-0) was trained on the MPtrj dataset β€” ~1.6 million bulk-crystal structures at DFT (PBE+U) level, spanning 89 elements β€” making it suitable for organic molecules, inorganic materials, battery electrolytes, catalysts, and more.


πŸ§ͺ Use Case 1: BGR β€” Batched Geometry Relaxation#

What it does: Given atomic coordinates, finds the lowest-energy (equilibrium) structure by relaxing forces to zero. Essential for validating molecular structures, finding transition states, and preparing input for further simulations.

Scientific Breakthrough Potential#

Research Area

Application

Impact

Battery Materials

Optimize Li-ion intercalation structures in cathode materials (NMC, LFP)

Accelerate discovery of higher-capacity battery chemistries

Catalyst Design

Relax adsorbate configurations on metal surfaces (Pt, Pd, Ni)

Screen thousands of catalyst candidates for green hydrogen, COβ‚‚ reduction

Drug Discovery

Optimize ligand-protein binding poses at near-DFT accuracy

Reduce false positives in virtual screening pipelines

OLED Materials

Relax excited-state geometries of organic emitters

Design more efficient organic light-emitting diodes

Thai Natural Products

Validate crystal structures of Thai medicinal compounds

Support computational pharmacology research at Mahidol

Quick Start β€” Single Molecule#

# H2 molecule geometry relaxation
curl -s -X POST \
  'https://aicenter.mahidol.ac.th/alchemi-bgr/v1/infer' \
  -H 'Content-Type: application/json' \
  -d '{
    "atoms": [{
      "coord": [0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
      "numbers": [1, 1],
      "cell": [10, 0, 0, 0, 10, 0, 0, 0, 10]
    }]
  }' | python3 -m json.tool

Expected output: converged: true, energy ~-6.5 eV, bond distance relaxed to 0.74 Angstrom.

Python β€” Batch Processing with ASE#

import requests
import ase.io
import numpy as np

INFER_URL = "https://aicenter.mahidol.ac.th/alchemi-bgr/v1/infer"

# Read multiple structures from extended XYZ file
atoms_list = ase.io.read("structures.extxyz", index=":")
if not isinstance(atoms_list, list):
    atoms_list = [atoms_list]

# Convert ASE Atoms to API format
def ase_to_api(atoms, sid=None):
    data = {
        'coord': atoms.positions.flatten().tolist(),
        'numbers': atoms.numbers.tolist(),
        'charge': atoms.info.get('charge', 0),
        'mult': atoms.info.get('mult', 1),
    }
    if atoms.cell.volume > 0:
        data['cell'] = atoms.cell.array.flatten().tolist()
        data['pbc'] = atoms.pbc.tolist()
    if sid:
        data['structure_id'] = sid
    return data

# Submit batch request
input_data = {'atoms': [ase_to_api(a, f"struct_{i}") for i, a in enumerate(atoms_list)]}
response = requests.post(INFER_URL, json=input_data)
result = response.json()

# Write optimized structures
optimized = []
for opt in result['atoms']:
    a = ase.Atoms(positions=np.array(opt['coord']).reshape(-1, 3), numbers=opt['numbers'])
    if opt.get('cell'):
        a.set_cell(np.array(opt['cell']).reshape(3, 3))
    a.info['energy'] = opt['energy']
    a.info['converged'] = opt['converged']
    optimized.append(a)

ase.io.write('structures_optimized.extxyz', optimized)
print(f"Optimized {len(optimized)} structures")

πŸ§ͺ Use Case 2: BMD β€” Batched Molecular Dynamics#

What it does: Simulates atomic motion over time using MLIP forces. Supports NVE (microcanonical), NVT (canonical with thermostat), and NPT (isothermal-isobaric) ensembles. Essential for studying temperature-dependent properties, phase transitions, diffusion, and conformational sampling.

Scientific Breakthrough Potential#

Research Area

Application

Impact

Solid-State Batteries

Simulate Li⁺ diffusion in solid electrolytes (LLZO, LATP) at operating temp

Predict ionic conductivity without expensive DFT-MD

Polymer Science

Study thermal behavior of polymer chains, glass transition temperatures

Design polymers with tailored mechanical properties

Protein-Ligand Dynamics

Run MD of drug binding events with near-DFT accuracy forces

Understand binding kinetics beyond static docking

Thermal Materials

Compute thermal conductivity via Green-Kubo from equilibrium MD

Discover thermoelectric materials for waste heat recovery

Nanoparticle Stability

Simulate surface reconstruction of metal nanoparticles under heat

Optimize catalyst stability at reaction conditions

Quick Start β€” NVT Simulation#

# Carbon dimer, 300K NVT simulation for 1 ps
curl -s -X POST \
  'https://aicenter.mahidol.ac.th/alchemi-bmd/v1/infer' \
  -H 'Content-Type: application/json' \
  -d '{
    "atoms": {
      "coord": [0.0, 0.0, 0.0, 1.5, 0.0, 0.0],
      "numbers": [6, 6],
      "cell": [10, 0, 0, 0, 10, 0, 0, 0, 10],
      "pbc": [true, true, true]
    },
    "config": {
      "temperature": 300.0,
      "nvt": true,
      "friction": 1.0,
      "dt": 1.0,
      "md_time_max": 1.0,
      "save_interval": 10
    }
  }' | python3 -m json.tool

Python β€” Full MD Workflow with Restart#

import requests

SERVER = "https://aicenter.mahidol.ac.th/alchemi-bmd/v1/infer"

# Initial simulation
request = {
    "atoms": {
        "coord": [0.0, 0.0, 0.0, 1.5, 0.0, 0.0],
        "numbers": [6, 6],
        "cell": [10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 10.0],
        "pbc": [True, True, True]
    },
    "config": {
        "temperature": 300.0,
        "dt": 1.0,
        "md_time_max": 1.0,
        "nvt": True,
        "save_interval": 10
    }
}

response = requests.post(SERVER, json=request)
result = response.json()

# Analyze trajectory
trajectory = result["trajectory"]
print(f"Total snapshots: {len(trajectory)}")
print(f"Final energy: {trajectory[-1].get('energy', 'N/A')}")

# Restart from final state
final = trajectory[-1]
restart = {
    "atoms": {
        "coord": final["coord"],
        "velocity": final["velocity"],
        "numbers": [6, 6],
        "cell": final.get("cell", request["atoms"]["cell"]),
        "pbc": [True, True, True]
    },
    "config": {
        "temperature": 300.0,
        "dt": 1.0,
        "nvt": True,
        "save_interval": 10,
        "istep": result["config"]["istep"],
        "md_time": result["config"]["md_time"],
        "md_time_max": float(result["config"]["md_time"]) + 1.0
    }
}

continuation = requests.post(SERVER, json=restart).json()
print(f"Continued: {len(continuation['trajectory'])} new snapshots")

Ensemble Configuration Reference#

Ensemble

Config Fields

Use Case

NVE

{"dt": 0.5, "md_time_max": 1.0}

Energy conservation tests, isolated systems

NVT

{"temperature": 300, "nvt": true, "friction": 1.0, "dt": 1.0, "md_time_max": 10}

Constant-temperature simulations (most common)

NPT

Add "npt": true, "pressure": 1.0, "barostat_every": 25

Constant pressure (material expansion, phase transitions)


πŸ§ͺ Use Case 3: Combined BGR + BMD Workflow#

Typical research pipeline: Relax structure first (BGR), then run dynamics from equilibrium (BMD).

import requests

BGR_URL = "https://aicenter.mahidol.ac.th/alchemi-bgr/v1/infer"
BMD_URL = "https://aicenter.mahidol.ac.th/alchemi-bmd/v1/infer"

# Step 1: Relax initial structure
bgr_request = {
    "atoms": [{
        "coord": [0.0, 0.0, 0.0, 0.0, 0.75, 0.0],  # Initial guess
        "numbers": [8, 8],  # O2 molecule
        "cell": [10, 0, 0, 0, 10, 0, 0, 0, 10]
    }]
}
relaxed = requests.post(BGR_URL, json=bgr_request).json()["atoms"][0]
# Note: API returns coord values as strings β€” cast to float for arithmetic
coord = [float(x) for x in relaxed['coord']]
print(f"Relaxed energy: {float(relaxed['energy']):.4f} eV")
bond_len = ((coord[3]-coord[0])**2 + (coord[4]-coord[1])**2 + (coord[5]-coord[2])**2)**0.5
print(f"Bond length: {bond_len:.3f} A")

# Step 2: Run MD from relaxed structure
bmd_request = {
    "atoms": {
        "coord": relaxed["coord"],
        "numbers": relaxed["numbers"],
        "cell": relaxed.get("cell", [10,0,0,0,10,0,0,0,10]),
        "pbc": [True, True, True]
    },
    "config": {
        "temperature": 500.0,  # High temp to study dissociation
        "nvt": True,
        "dt": 0.5,
        "md_time_max": 2.0,
        "save_interval": 5
    }
}
md_result = requests.post(BMD_URL, json=bmd_request).json()
print(f"MD trajectory: {len(md_result['trajectory'])} snapshots over {md_result['config']['md_time']:.1f} ps")

πŸ”Œ Integration with AI Agents (Qwen / Hermes)#

ALCHEMI endpoints can be called directly from AI coding agents for autonomous materials discovery:

Continue.dev / VS Code Configuration#

Add to ~/.continue/config.yaml:

models:
  - name: alchemi-assistant
    provider: openai
    model: qwen
    apiBase: https://aicenter.mahidol.ac.th/qwen/v1
    apiKey: "dummy"
    systemMessage: |
      You are a computational chemistry assistant. You have access to
      NVIDIA ALCHEMI endpoints for geometry relaxation and molecular dynamics.
      BGR: https://aicenter.mahidol.ac.th/alchemi-bgr/v1/infer
      BMD: https://aicenter.mahidol.ac.th/alchemi-bmd/v1/infer

Hermes Agent Skill#

Create ~/.hermes/skills/alchemi/SKILL.md for automated chemistry workflows:

---
name: alchemi
description: "Use when running atomistic simulations β€” geometry relaxation (BGR) or molecular dynamics (BMD) via NVIDIA ALCHEMI NIM endpoints."
tags: [chemistry, materials-science, mlip, molecular-dynamics, geometry-relaxation]
---

With tool definitions for calling the REST API, parsing results, and integrating with ASE/pymatgen workflows.


πŸ§ͺ Verification & Testing#

Health Check#

# BGR health
curl -sk 'https://aicenter.mahidol.ac.th/alchemi-bgr/v1/health/ready'
# Expected: {"status":"ready","backends_alive":2,"backends_total":2}

# BMD health
curl -sk 'https://aicenter.mahidol.ac.th/alchemi-bmd/v1/health/ready'
# Expected: {"status":"ready","backends_alive":2,"backends_total":2}

Quick Inference Test#

# H2 relaxation test
curl -sk -X POST 'https://aicenter.mahidol.ac.th/alchemi-bgr/v1/infer' \
  -H 'Content-Type: application/json' \
  -d '{"atoms":[{"coord":[0,0,0,0,0,1],"numbers":[1,1],"cell":[10,0,0,0,10,0,0,0,10]}]}'

Expected: converged: true, energy ~-6.5 eV, bond distance ~0.74 A.


πŸ›  Troubleshooting#

Symptom

Action

503 Service Unavailable

The NIM is still initializing (model download + batch estimation). The liveness probe itself doesn’t check the pod until 10 minutes after start, so a fresh deployment can stay unready for up to 10 minutes β€” wait and retry rather than assuming a crash.

504 Gateway Timeout

Increase NGINX proxy timeout. Large batches may take longer.

converged: false

Structure did not relax within max steps. Try different initial geometry or increase optimizer iterations.

Empty trajectory in BMD

Check that md_time_max > 0 and dt is reasonable (0.5-2.0 fs).

Wrong element numbers

API uses atomic numbers (H=1, C=6, O=8, Fe=26), not symbols.

Periodic vs non-periodic

For isolated molecules, omit cell field or set pbc: [false,false,false].

coord/energy returned as strings

The API serializes numeric values as JSON strings. Cast with float() before arithmetic: coord = [float(x) for x in atom['coord']].

Concurrent Requests#

Both endpoints support multiple concurrent requests. Issue parallel requests from separate threads/processes for throughput:

import aiohttp
import asyncio

async def relax_batch(session, structures):
    payload = {"atoms": structures}
    async with session.post("https://aicenter.mahidol.ac.th/alchemi-bgr/v1/infer", json=payload) as resp:
        return await resp.json()

async def main():
    async with aiohttp.ClientSession() as session:
        results = await asyncio.gather(
            relax_batch(session, batch_1),
            relax_batch(session, batch_2),
            relax_batch(session, batch_3)
        )
    return results

πŸ“ Usage Notes#

  • Accuracy: MACE-MP-0 achieves an energy MAE on the order of 10-20 meV/atom vs DFT on the MPtrj benchmark β€” comparable to hybrid functionals at a fraction of the cost.

  • Element coverage: Trained on 89 elements (H through Pu). Best accuracy for elements common in materials science (C, N, O, Si, transition metals).

  • Batch size: The server auto-estimates optimal batch size per GPU (~4000 atoms per backend on A100). Submit larger batches for better throughput.

  • Privacy: All data remains within Mahidol University infrastructure. No external data transfer.

  • Rate limiting: No explicit rate limit, but be mindful of shared GPU resources (4 GPUs used by ALCHEMI).

  • No authentication required for internal cluster access. External access requires VPN/proxy configuration.


πŸ“š References#

Resource

URL

NVIDIA ALCHEMI Overview

https://developer.nvidia.com/cuda/cuda-x-libraries/alchemi

BGR Documentation

https://docs.nvidia.com/nim/alchemi/alchemi-bgr/latest/

BMD Documentation

https://docs.nvidia.com/nim/alchemi/alchemi-bmd/latest/

MACE Model Paper

https://arxiv.org/abs/2206.07697

ALCHEMI Toolkit (Python)

https://github.com/NVIDIA/nvalchemi-toolkit

ASE (Atomic Simulation Env)

https://wiki.fysik.dtu.dk/ase/


Last Updated: 2026-07-22