Skip to content

DCM and ACO dimer scans (cutoffs + LR solvers)

Rigid COM-distance scans for DCM:2 and ACO:2 dimers, sweeping MM nonbond modes and long-range Coulomb backends. Same philosophy as the DCM:3 NVE cutoff sweep (workflows/dcm3_nve_cutoff_sweep) and the MEOH distance scan (scripts/scan_meoh_dimer_distance.py), but focused on hybrid energy vs COM with solver comparison.

What you get

Each run writes scan_1d.npz with decomposed energies on a COM grid (d₀₁):

Field Meaning
scan_2d_hybrid_energy_kcal Total hybrid USER energy
scan_2d_ml_2b_E_kcal PhysNet dimer (ML two-body)
scan_2d_mm_E_kcal Switched JAX MM
lr_solver_active Resolved backend (mic, ewald, jax_pme, …)
ewald_omit_self Whether --ewald-omit-self was set (hybrid-native Ewald)
mm_nonbond_mode jax_mic or periodic_external

Vertical lines at 6.5 / 8 / 13 Å mark default cutoff regions (see hybrid-potential-regions.md).

Prerequisites

export MMML_CKPT=/path/to/checkpoint   # DCM or ACO PhysNet
uv sync --extra gpu                    # or CPU JAX for smoke tests
# OpenMPI + libcharmm — use scripts/mmml-charmm-mpirun.sh

Full solver sweep (DCM + ACO)

chmod +x scripts/run_dcm_aco_dimer_lr_scans.sh
./scripts/run_dcm_aco_dimer_lr_scans.sh
scan_tag mm_nonbond_mode lr_solver Notes
vacuum_mic jax_mic mic Free space; pair-loop MIC only
pbc_mic jax_mic mic Periodic box; truncated Coulomb
pbc_hybrid_ewald jax_mic ewald Hybrid-native full-box Ewald (train↔MD); includes self term
pbc_hybrid_ewald_omit_self jax_mic ewald Same + --ewald-omit-self (MIC/non-Ewald-trained models)
pbc_jax_pme_ewald jax_mic jax_pme jax-pme method=ewald; + Coulomb & r⁻⁶ tail
pbc_jax_pme_pme jax_mic jax_pme PME mesh
pbc_jax_pme_p3m jax_mic jax_pme P3M
pbc_jax_pme_ewald_no_disp jax_mic jax_pme Coulomb-only LR
pbc_periodic_external_jax_pme_pme periodic_external jax_pme Full-box Coulomb + CHARMM LJ
pbc_periodic_external_nvalchemiops periodic_external nvalchemiops_pme If mmml[nvalchemiops-pme] installed
pbc_periodic_external_scafacos_ewald periodic_external scafacos If SCAFACOS_LIB set

lr_solver=ewald is not the same as jax_pme --jax-pme-method ewald. The hybrid-native tags above are the parity lane for liquid md-system --lr-solver ewald.

Environment knobs:

BOX_SIZE=40 SCAN_MIN=4.0 SCAN_MAX=15.0 SCAN_STEPS=16 \
  COMPOSITIONS="DCM:2" SKIP_PERIODIC=1 \
  ./scripts/run_dcm_aco_dimer_lr_scans.sh

SKIP_PERIODIC=1 skips periodic_external legs (no ScaFaCoS / nvalchemiops required).

Single manual scan

Hybrid-native Ewald (train↔MD parity; omit self for MIC-trained ckpts):

export MMML_CKPT=/path/to/dcm_ckpt
./scripts/mmml-charmm-mpirun.sh python scripts/scan_mlpot_dimer_2d_pycharmm.py \
  DCM:2 --scan-1d --scan-tag pbc_hybrid_ewald_omit_self \
  --box-size 36 --mlpot-pbc --lr-solver ewald --ewald-omit-self \
  --scan-2d-min 3.5 --scan-2d-max 14.0 --scan-2d-steps 12 \
  --output-dir artifacts/dimer_lr_scans

jax-pme Ewald method (separate backend):

export MMML_CKPT=/path/to/dcm_ckpt
./scripts/mmml-charmm-mpirun.sh python scripts/scan_mlpot_dimer_2d_pycharmm.py \
  DCM:2 \
  --scan-1d \
  --scan-tag pbc_jax_pme_ewald \
  --box-size 36 --mlpot-pbc \
  --lr-solver jax_pme --jax-pme-method ewald \
  --scan-2d-min 3.5 --scan-2d-max 14.0 --scan-2d-steps 12 \
  --mm-switch-on 8 --mm-switch-width 5 --ml-switch-width 1.5 \
  --packmol-sphere --packmol-radius 10 \
  --output-dir artifacts/dimer_lr_scans

ACO example (same flags, different residue):

./scripts/mmml-charmm-mpirun.sh python scripts/scan_mlpot_dimer_2d_pycharmm.py \
  ACO:2 --scan-1d --scan-tag vacuum_mic --free-space --lr-solver mic \
  --output-dir artifacts/dimer_lr_scans

Trimer / 2D grid (legacy path, e.g. cutoff geometry panels):

./scripts/run_mlpot_dimer_2d_scans.sh DCM:3

Plot comparison

uv run python scripts/plot_dimer_lr_scan_compare.py --root artifacts/dimer_lr_scans
# → artifacts/dimer_lr_scans/plots/dcm_2_lr_compare.png
# → artifacts/dimer_lr_scans/plots/aco_2_lr_compare.png

Unit tests (no PyCHARMM)

uv run pytest tests/unit/test_dimer_lr_scan_lib.py tests/unit/test_trimer_scan_geometry.py -q