Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
28b1093
add qmmm devoloped by Miquel
mohsenkor Nov 6, 2024
ab7afca
New feature allowing QM/MM MD dynamics using OpenMM as MD engine and …
huixrotllant Nov 7, 2024
f992b33
Revert "New feature allowing QM/MM MD dynamics using OpenMM as MD eng…
huixrotllant Nov 7, 2024
2475f6c
New feature allowing QM/MM MD dynamics using OpenMM as MD engine and …
huixrotllant Nov 7, 2024
e17d082
Bug correction for the default forcefield
huixrotllant Nov 7, 2024
7b1422b
Bug correction for QM/MM MD dynamics with OpenMM
huixrotllant Nov 13, 2024
37c1626
Merge branch 'main' into qmmm
huixrotllant Jan 22, 2025
2f685c6
fix:ttt => ttt(:nat,:npts)
mohsenkor Mar 10, 2025
21d5a41
add_potqm_contributions
mohsenkor Nov 25, 2025
9f0cca8
Merge branch 'qmmm' into qmmm_merged
mohsenkor Nov 26, 2025
26ce6fb
Merge pull request #1 from mohsenkor/qmmm_merged
mohsenkor Nov 26, 2025
fccbcc3
feat:qmmm using python interface
mohsenkor Dec 4, 2025
25a8674
fix: scf run issue
mohsenkor Dec 9, 2025
6fea6e3
add: qmmm_driver.py
mohsenkor Dec 9, 2025
3aa51ea
energy convergence
mohsenkor Mar 24, 2026
3ece116
add example
mohsenkor Mar 24, 2026
83c9e6a
add example2
mohsenkor Mar 24, 2026
97afd57
feat: simulation manager
mohsenkor Apr 2, 2026
338cf91
feat:Mulliken population of states
mohsenkor Apr 14, 2026
d216919
feat:qmmm tdhf calculation
mohsenkor May 6, 2026
4c74327
Merge mohsenkor/feat/qmmm: ESPF QM/MM foundation for NAMD-QMMM
karmachoi Jun 7, 2026
424d11a
feat(namd): native Tully FSSH nonadiabatic MD (runtype=namd), gas phase
karmachoi Jun 7, 2026
289eaf1
fix(qmmm): non-periodic electrostatic embedding crashed (POTQM missing)
karmachoi Jun 7, 2026
a8a65ea
feat(namd): QM/MM NAMD driver (ESPF electrostatic embedding, non-peri…
karmachoi Jun 7, 2026
0c961ed
wip(namd): PBC (PME) plumbing for QM/MM NAMD — runs, forces incomplete
karmachoi Jun 7, 2026
aa9cc54
wip(namd): add QM-QM Ewald correction force; diagnose periodic drift …
karmachoi Jun 7, 2026
ad4b5da
feat(namd): norm-preserving interpolation (NPI) time-derivative coupl…
karmachoi Jun 7, 2026
0d5e531
Merge remote-tracking branch 'upstream/main' into namd-qmmm
karmachoi Jun 7, 2026
09205dd
refactor(namd): generalize FSSH kernel to arbitrary state count (enab…
karmachoi Jun 7, 2026
f06a346
feat(namd): SOC-NAMD (ISC) on the SHARC spin-adiabatic representation
karmachoi Jun 7, 2026
e38f570
feat(namd): ISC hopping layer for SOC-NAMD (SHARC, U-phase tracking)
karmachoi Jun 7, 2026
b92660f
SOC-NAMD: weighted-MCH diagonal gradient + substep LD propagator
karmachoi Jun 7, 2026
2e82eba
Add NAMD_SOC_QMMM: SOC-NAMD (ISC) with ESPF QM/MM embedding
karmachoi Jun 7, 2026
d6ccf8b
SOC-NAMD: fix active-state handling for the spin-adiabatic manifold
karmachoi Jun 8, 2026
e0963dd
SOC-NAMD: correct singlet gradient target mapping + S0 guard
karmachoi Jun 8, 2026
ade35ab
SOC-NAMD: correct MRSF root convention (S0 = lowest root, target 1)
karmachoi Jun 8, 2026
032c0b1
NAMD_SOC_QMMM: borrow SOC helper methods so self-dispatch resolves
karmachoi Jun 8, 2026
17d967d
Fix periodic (PME) QM/MM NAMD energy conservation: zero the buggy POTQM
karmachoi Jun 8, 2026
0108494
SOC-NAMD: select initial active state by spin character ([md] init_st…
karmachoi Jun 8, 2026
56251e3
NAMD QM/MM: SHAKE/RATTLE rigid-water constraints in the velocity-Verl…
karmachoi Jun 8, 2026
2bcf385
SOC-NAMD-QMMM: continuous diagonal gradient + constrained-start therm…
karmachoi Jun 8, 2026
8df0bf0
SOC-NAMD: optional [md] econs - temporary E_tot-conservation rescale
karmachoi Jun 8, 2026
f202b04
NAMD: optional adaptive (variable) timestep [md] dt_adaptive
karmachoi Jun 8, 2026
b9924f1
Merge remote-tracking branch 'upstream/main' into namd-qmmm
karmachoi Jun 8, 2026
bd20dd9
ESPF QM/MM: complete analytic gradient + smooth-switching grid (new d…
karmachoi Jun 8, 2026
85cba6e
ESPF: fix layer-scaled exclusion → stable fixed-scale exclusion
karmachoi Jun 8, 2026
813f98b
feat(qmmm): add ESPF_GAMESS=1 mode for GAMESS-identical LEBGRD grid
karmachoi Jun 9, 2026
8c169d2
feat(qmmm): add ESPF_ROHF=1 mode for GAMESS-comparable validation
karmachoi Jun 9, 2026
f786cc9
fix(namd): honour ESPF_ROHF=1 in SOC gradient loop
karmachoi Jun 9, 2026
41fc343
fix(namd): include ΔE_ESPF in velocity rescaling at ISC hops
karmachoi Jun 9, 2026
58b37cb
docs(namd): recommend thrshe=0.1 Ha for SOC-NAMD in comment
karmachoi Jun 9, 2026
8750d7f
docs(namd): add SOC energy conservation improvement plan
karmachoi Jun 9, 2026
c06ed96
feat(namd): add SOC MCH-basis option
karmachoi Jun 9, 2026
5055a62
fix(namd): stabilize QMMM PME and overlap tracking
karmachoi Jun 9, 2026
859837f
Document and guard SOC-QMMM production mode
karmachoi Jun 9, 2026
a18d7c2
Merge remote-tracking branch 'upstream/main' into codex/soc-namd-options
karmachoi Jun 13, 2026
4e627e5
Remove optional DLFIND startup dependency
karmachoi Jun 13, 2026
8efd0b2
Merge remote-tracking branch 'upstream/main' into codex/soc-namd-options
karmachoi Jun 13, 2026
2c16c02
Address SOC-QMMM PR review findings
karmachoi Jun 13, 2026
7b1bb75
Update README for NAMD and native optimizer
karmachoi Jun 13, 2026
c4bc21f
Merge branch 'main' into codex/soc-namd-options
karmachoi Jun 13, 2026
f711b48
Fix review findings in MRSF NAMD / SOC-NAMD / ESPF QM/MM
karmachoi Jun 17, 2026
5b19b6d
Merge upstream/main into codex/soc-namd-options
karmachoi Jun 17, 2026
d951f15
Remove top-level docs/ folder
karmachoi Jun 17, 2026
7d23022
Drop stale references to removed docs/ files
karmachoi Jun 17, 2026
457a6e0
Fix QM/MM input validation for .pdb systems and 'None' constraints
claude Jul 2, 2026
5cf1375
QM/MM: link-atom connectivity for bonds cut by the QM/MM boundary
claude Jul 2, 2026
471854d
QM/MM driver: correct ESPF gradient reshape and MM-charge update for …
claude Jul 2, 2026
b4f91f1
chore: ignore oqp_project.json run artifact
claude Jul 2, 2026
71e0dc8
QM/MM: experimental full-ESPF electrostatics for covalent boundaries …
claude Jul 3, 2026
fac2be8
QM/MM full-ESPF: add nuclear-MM energy -> FD-exact covalent-boundary …
claude Jul 3, 2026
e0f90da
QM/MM full-ESPF: periodic (PBC) support + wire into NAMD / QMMM_MD
claude Jul 3, 2026
36e5ace
QM/MM: make full-ESPF the default for electrostatic embedding
claude Jul 3, 2026
a841fae
Merge upstream/main into codex/soc-namd-options
karmachoi Jul 3, 2026
68bbeea
build: migrate NAMD/QM/MM Fortran to main's tagarray container API
karmachoi Jul 3, 2026
41022c9
feat(python-api): pythonic QM/MM and NAMD setup on the OpenQP wrapper
karmachoi Jul 3, 2026
ca24242
Merge branch 'main' into codex/soc-namd-options
karmachoi Jul 3, 2026
b88f7d8
Merge branch 'main' into codex/soc-namd-options
karmachoi Jul 3, 2026
efbdf73
ci: classify NAMD/QM/MM feature flags and skip QM/MM examples in the …
karmachoi Jul 3, 2026
0182881
examples(QMMM): add minimal NAMD-QMMM demonstrations (H2CO in water)
karmachoi Jul 3, 2026
dd930ba
examples(QMMM): include NAMD-QMMM examples in run_tests all (skip if …
karmachoi Jul 3, 2026
ad43fae
blas: route ESPF dgels through the ILP64 wrapper; fix macOS Accelerat…
karmachoi Jul 3, 2026
39bfc43
docs(readme): describe SOC-NAMD-QMMM in the Dynamics & QM/MM section
karmachoi Jul 3, 2026
b217f46
Merge codex/soc-namd-options: full-ESPF covalent-boundary QM/MM under…
karmachoi Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 193 additions & 0 deletions docs/qmmm-tb-reconciliation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# QM/MM ↔ tight-binding reconciliation (full-ESPF covalent boundary for `method=dftb` and `method=xtb`)

This note records the merge of `origin/codex/soc-namd-options` (the correct
full-ESPF covalent-boundary QM/MM) into the TB-adapter branch
(`feat/openqp-xtb-adapter`: DFTB adapter PR #266 + the `method=xtb` adapter + the
`oqp.utils.tb_backends` dispatch generalization). The goal is a single tree where
the full-ESPF QM/MM driver internals coexist with the TB dispatch so that
`method=dftb` **and** `method=xtb` QM/MM both conserve energy at covalent
(hydrogen link-atom) boundaries.
Comment on lines +7 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add an example for TB QM/MM

This change explicitly introduces method=dftb/method=xtb QM/MM at covalent link-atom boundaries, but the diff does not add any examples/** input that exercises that new user-facing path (and it deletes the only dedicated covalent-boundary QMMM-MD deck). AGENTS.md rule 2 requires new capabilities to ship with a small, fast example, so users and CI have no example-level coverage for the feature this reconciliation enables.

Useful? React with 👍 / 👎.

Comment on lines +7 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Link the companion openqp-docs PR

Because this change advertises new user-facing method=dftb/method=xtb QM/MM support at covalent boundaries, AGENTS.md rule 4 requires the PR description to link the companion openqp-docs manual update. No such link is present in the submitted description, so the keyword/workflow manual can drift from the behavior enabled here.

Useful? React with 👍 / 👎.


Merge-base: `55befcb8f` (PR #253). `soc-namd-options` was 83 commits ahead in
QM/MM; the TB branch was 13 commits ahead. The merge was performed
`soc-namd-options → feat/xtb-qmmm-fullespf`.

## What full-ESPF brings

The released ESPF path embedded covalent boundaries with **frontier-charge
redistribution** (`frontier_scheme = none|rcd|rc|z1`, PR #258): the M1 host
charge could be deleted/redistributed onto virtual midpoint charges. `soc-namd-
options` replaced that with a cleaner, gradient-exact **full-field ESPF** scheme
and removed the redistribution machinery entirely:

- `OpenQpQMMM.__init__` builds a per-QM-centre MM-exclusion structure
(`_build_qm_mm_exclusions`) instead of a frontier-host redistribution map. The
embedding potential (`_full_field_potmm`) and the coupling force
(`_coupling_forces`) use the *same* per-centre view of the MM charges, so the
analytic gradient stays exact across a covalent cut.
- The full-ESPF native path adds the **nuclear-MM interaction** `Σ_A Z_A φ_A`
to complete the QM–MM electrostatic energy (commit `fac2be89c`, "nuclear-MM
energy → FD-exact covalent-boundary forces"), and drops the frontier
redistribution / virtual-site scatter.
- `espf_full` is now selected by `Embedding ∈ {espf, espf_full, electrostatic}`
and is the default.
- PBC / min-image support (`_box_lengths_bohr`, `_min_image`) is retained.

The `redistribute_frontier_charges` / `assemble_embedding_sites` helpers,
`_frontier_hosts` / `_embedding_sites`, the `frontier_scheme` schema key and API
parameter, and the frontier tests/examples were all removed on `soc-namd-options`;
this merge takes that removal.

## TB dispatch contract (unchanged by full-ESPF)

For `method=dftb`/`xtb` the openqp-dftb/openqp-xtb library folds the per-QM-centre
MM potential (Hartree/e) **directly into the SCC Hamiltonian** via
`mol.dftb_external_potential = POTMM`:

- the returned state energy is the **complete** embedded QM energy (it already
contains `E_ext = Σ_A q_A φ_A` with `q_A` the *net* atomic charge), so the
driver must **not** add the native nuclear `Σ_A Z_A φ_A` term for TB;
- the returned analytic gradient is `d(E_embedded)/dR_QM` at fixed potential (the
Pulay/charge-response coupling is already inside it), so the native
`espf_op_corr` hcore mutation and `grad_esp_qmmm(_excited)` / `OQP::ESPF_GRAD`
additions are **skipped**;
- the adapter publishes relaxed net atomic charges of the active state into
`OQP::partial_charges`; the driver's backend-agnostic `_coupling_forces` reads
those for the classical `dφ/dR` MM-field forces (the DFTB analog of
`form_esp_charges`).

Only full-ESPF (`espf_full`) or mechanical (`potmm is None`) embedding is
supported for TB; the legacy `split` scheme is rejected (it would double-count
the coupling already inside the embedded TB energy).

## TB-dispatch call sites re-applied on the full-ESPF driver

Dispatch helpers live in `pyoqp/oqp/utils/tb_backends.py`:
`is_tb_method`, `tb_section_name`, `tb_config`, `make_tb_adapter`.

`pyoqp/oqp/library/qmmm_driver.py` (`OpenQpQMMM`):

- import `is_tb_method`;
- `_forces_qm`, **mol mode** — after `_update_mol_positions()`, before the native
`SinglePoint`/`espf_op_corr` path: `if is_tb_method(...): return
self._forces_qm_dftb(self.mol, potmm)`;
- `_forces_qm`, **config mode** — after `self.op = OPENQP(...)`, same early
dispatch on `self.op.mol`;
- new method `_forces_qm_dftb(mol, potmm)`: sets `mol.dftb_external_potential`,
runs `Gradient(mol).gradient()` (dispatches to the TB adapter), reads the active
state energy/gradient and `OQP::partial_charges`; guards `espf_full` (else
`NotImplementedError`).

`pyoqp/oqp/library/namd.py`:

- import `is_tb_method, make_tb_adapter, tb_section_name`;
- `NAMD_QMMM._electronic_structure` — TB branch sets `mol.dftb_external_potential`
and runs the embedded SCF/excitation without the ESPF hcore mutation
(covalent-boundary electronic step);
- `NAMD_QMMM._forces_qm` — TB early-return of the raw gradient (skips
`grad_esp_qmmm`/`OQP::ESPF_GRAD`);
- `NAMD_QMMM._total_force` — TB energy uses `mol.energies[active]` with **no**
nuclear `Σ Z_A φ_A` term;
- `NAMD_SOC`, `NAMD_SOC_MCH`, `NAMD_SOC_QMMM`, `NAMD_SOC_MCH_QMMM` — TB SOC arms:
`tb_section_name(...)['target_multiplicity']` bookkeeping, `_dftb_soc_tags`
(one-centre SOC + numpy `eigh`) in place of `oqp.soc_mrsf`, and
`_dftb_spatial_overlap` in place of `oqp.get_states_overlap`;
- module helpers `_dftb_soc_tags`, `_dftb_spatial_overlap` (TB, dftb+xtb via
`make_tb_adapter`).

`pyoqp/oqp/library/runfunc.py` — `compute_soc` TB branch (`xtb_soc`/`dftb_soc`);
`compute_namd` (soc's QM/MM NAMD dispatch) retained.

`pyoqp/oqp/library/single_point.py` — TB dispatch at `energy`, `reference`,
`excitation`, `gradient`, and the `dftb_overlap`/`dftb_states_overlap` state-
overlap paths (all via `is_tb_method`/`make_tb_adapter`); soc's
`import oqp.utils.qmmm` and `scf_grad` tweaks retained.

`pyoqp/oqp/utils/input_checker.py` — NAMD gate allows
`method ∈ {tdhf, dftb, xtb}`; the `method=dftb/xtb` QM/MM validator (rejects
`split`, requires full-ESPF electrostatic, gates SOC-QMMM off as "not yet wired")
retained from the TB branch and now describes the full-ESPF scheme.

`pyoqp/oqp/molecule/oqpdata.py` — `[dftb]`/`[xtb]` schema sections retained;
`frontier_scheme` removed.

`pyoqp/oqp/openqp.py` — `[dftb]`/`[xtb]` builder API retained; `frontier_scheme`
argument removed from `qmmm(...)`.

`pyoqp/oqp/utils/oqp_tester.py` — openqp-dftb/openqp-xtb "backend not found →
SKIPPED" handling and the `method=dftb`/`method=xtb` example-skip predicate
retained.

## Conflict resolution per file

| File | Type | Resolution |
| --- | --- | --- |
| `pyoqp/oqp/library/namd.py` | add/add | Take soc (full-ESPF), re-apply the TB delta (`674aab601..HEAD`), which applied cleanly (soc namd.py ≡ released namd.py apart from the 2-line `frontier_scheme` removal). |
| `pyoqp/oqp/library/qmmm_driver.py` | add/add | Take soc (full-ESPF); re-apply the TB delta — 3/4 hunks clean, the `tb_backends` import added manually (soc had edited the adjacent `qmmm_connectivity` import). |
| `pyoqp/oqp/library/qmmm_connectivity.py` | add/add | Take soc (frontier helpers removed). TB delta never touched this file. |
| `pyoqp/oqp/library/qmmm_md.py` | add/add | Take soc (removes `frontier_scheme` + the internal `runtype→energy` forcing). TB dispatch is in the driver, not here. |
| `pyoqp/oqp/utils/qmmm.py` | (auto) | Identical on both sides; auto-merged. |
| `pyoqp/oqp/utils/input_checker.py` | content | Take HEAD for the NAMD `method ∈ {tdhf,dftb,xtb}` gate; rest auto-merged (soc QM/MM checks + TB validator both present). |
| `pyoqp/oqp/molecule/oqpdata.py` | content | Take HEAD `timestep` (`float`, safer than soc's `int` — the MD/NAMD code casts to float and `int` truncates sub-fs steps); take soc (remove `frontier_scheme`). `[dftb]`/`[xtb]` sections auto-merged. |
| `pyoqp/oqp/openqp.py` | content | Take soc (remove `frontier_scheme` param/docstring/update). `[dftb]`/`[xtb]` API auto-merged. |
| `pyoqp/oqp/utils/oqp_tester.py` | content | Take HEAD (openqp-dftb/xtb SKIPPED handling + skip predicate). |
| `pyoqp/oqp/library/runfunc.py` | (auto) | Auto-merged: soc `compute_namd`/`QMMMOpt` + TB `compute_soc` branch both present. |
| `pyoqp/oqp/library/single_point.py` | (auto) | Auto-merged: soc `import qmmm`/`scf_grad` + TB dispatch both present. |
| `include/oqp.h`, `source/tagarray_driver.F90` | (auto) | Auto-merged; soc additions verified present. |
| `tests/test_openqp_api.py` | content | Take soc (drop `frontier_scheme` schema + `test_qmmm_frontier_scheme_sets_section_key`); TB tests auto-merged. |
| `tests/test_rohf_status_and_interface.py` | content | Take HEAD (the `tb_backends` stub bootstrap the shared `try` block depends on). |
| `README.md`, `examples/QMMM/README.md` | content/add | Take HEAD tutorial links in README; take soc for the examples README (drop the `frontier_scheme` section). |
| `tests/test_qmmm_frontier.py`, `tests/test_qmmm_frontier_openmm.py`, `examples/QMMM/ala-dipeptide_BHHLYP-QMMM-MD-RCD.inp` | stale | **Removed** — HEAD-only artifacts of the removed `frontier_scheme` feature; they import `redistribute_frontier_charges`/`assemble_embedding_sites` (deleted on soc) and would fail to load. Absent on soc. |

Adapter files `pyoqp/oqp/library/openqp_dftb.py`, `openqp_xtb.py`,
`pyoqp/oqp/utils/tb_backends.py` are TB-branch-only (no conflict) and kept as-is.

## Static verification (this agent)

- Every changed `.py` file parses (`ast.parse`).
- No conflict markers remain in the tree.
- Dependency-free unit tests (no compiled `liboqp`): the DFTB/XTB schema-hook
tests, the runfunc/interface dispatch test, and the QM/MM builder API test pass
— **54 passed, 20 skipped** (skips are OpenMM/liboqp-gated).
- Full `tests/` run vs the pre-merge HEAD baseline: **identical set of 51
pre-existing failures** (all require the compiled `oqp` extension, which is not
built in this environment) — the merge introduces **no new failures**. The
drop in passing count equals exactly the removed frontier tests.

## Remaining runtime-validation checklist (needs the integrated runtime)

The compiled `_oqp`/`liboqp` extension plus the external openqp-dftb / openqp-xtb
libraries are **not** built in this agent's environment, so the numeric
covalent-boundary behaviour was not exercised. Once the integrated runtime is up:

1. **Covalent-boundary energy-vs-force FD, `method=dftb`** — a QM/MM partition
that cuts a covalent bond (H link-atom cap), full-ESPF electrostatic
embedding, `runtype=grad`: verify `F ≈ −dE/dR` by finite differences on both
QM and frontier/host MM atoms (this is the original DFTB QM/MM bug this merge
targets).
2. **Same FD check for `method=xtb`.**
3. **Whole-molecule QM/MM regression** (no link atom) for dftb and xtb — confirm
full-ESPF still matches the pre-merge energies/forces.
4. **Ground-state QM/MM MD** (`runtype=md`, `QMMM_MD`) energy conservation for
dftb and xtb across a covalent boundary.
5. **NAMD-QMMM** (`runtype=namd`, non-SOC, `embedding=electrostatic`) for dftb —
the `NAMD_QMMM._electronic_structure`/`_forces_qm`/`_total_force` TB arms.

### Honest flags for the runtime tests

- **`_forces_qm_dftb` is the released method name/body applied onto soc's driver.**
Its `espf_full` guard and its reliance on `_coupling_forces` reading
`OQP::partial_charges` are consistent with soc's `_coupling_forces` (verified
by reading both), but the *numerical* interaction of the TB net-charge coupling
with soc's **new full-field exclusion structure** (`_build_qm_mm_exclusions`,
which in practice applies *no* exclusions — see its NOTE) has not been run.
Item 1/2 above is the authoritative check.
- **SOC-QMMM for TB.** `namd.py` carries TB SOC-QMMM arms
(`NAMD_SOC_QMMM`/`NAMD_SOC_MCH_QMMM`), but `input_checker` still gates
`dftb/xtb` SOC-QMMM off as "not yet wired". The code path exists but is not
reachable through the checker; do not assume it is validated.
- **`qmmm_md.py`** dropped soc's removal of the internal `runtype→energy`
forcing block. The TB QM/MM MD path routes through
`OpenQpQMMM._forces_qm` (which has the TB dispatch), so this is expected to be
fine, but a `runtype=md` dftb/xtb smoke run (item 4) should confirm the QM
sub-run accepts the config.
39 changes: 0 additions & 39 deletions examples/QMMM/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,42 +39,3 @@ contract and the compact `job.qmmm(...)` / `job.workflow.namd(...)` Python API.
`ala.inp` and `2E4E_RHF-DFT-QMMM_energy.inp` are QM/MM single-point energy decks
(QM selection via `[input] system = file.pdb <indices>`); `run.inp` is a
ground-state OpenMM-integrator QM/MM MD deck.

## Covalent QM/MM boundary — `[qmmm] frontier_scheme`

When the QM/MM partition cuts a covalent bond, the dangling QM bond is capped
with a hydrogen link atom and the MM host atom (`M1`) sits ~1.5 Å from the QM
density. `[qmmm] frontier_scheme` selects how that frontier charge is treated in
the ESPF electrostatics. Covalent QM/MM boundaries are handled by the
ground-state QM/MM MD path (`QMMM_MD`); the nonadiabatic `runtype=namd` path does
not yet append link atoms to its QM molecule and raises on a covalent cut.

| value | meaning |
| --- | --- |
| `none` (default) | Full-field: the QM density sees the complete MM charge set. This is the **validated ESPF baseline** — ESPF couples the MM potential to QM *atomic-charge operators* (`h += Σ_A φ_A Q̂_A`, Huix-Rotllant & Ferré, *JCTC* 2021, 17, 538, eq 6), which already suppresses the electron spill-out that motivates redistribution in density-based embedding, so the ESPF papers use full MM charges even at a covalent protein boundary. |
| `rcd` | Delete `M1`'s charge and redistribute it to virtual point charges at the `M1–M2` bond midpoints, conserving the **total charge and the dipole about `M1`**. Gradient-consistent (the midpoints are linear in the real atom positions). |
| `rc` | As `rcd` but conserving only the total charge. |
| `z1` | Delete `M1`'s charge (conserves neither; for comparison). |

`rcd`/`rc`/`z1` are **optional refinements**, not the ESPF default. Enable via the
input (`[qmmm] frontier_scheme = rcd`) or the Python API
(`job.qmmm(..., frontier_scheme="rcd")`). It is a no-op for whole-molecule QM
regions (no cut bond).

A runnable covalent-boundary deck is
`ala-dipeptide_BHHLYP-QMMM-MD-RCD.inp` — the alanine dipeptide (ACE-ALA-NH2) with
AMBER-14, QM = the C-terminal amide so the QM/MM partition cuts the `ALA C–CA`
backbone bond, run as ground-state QM/MM MD (`runtype=md`) with
`frontier_scheme=rcd`:

```bash
cd examples/QMMM && openqp ala-dipeptide_BHHLYP-QMMM-MD-RCD.inp
```

Like the other ground-state QM/MM decks it is skipped by `openqp --run_tests all`
(covalent-boundary QM/MM is the ground-state MD path, not `runtype=namd`). The
same alanine boundary is exercised automatically — link-atom detection +
frontier-charge conservation on the real AMBER-14 charges — in
`tests/test_qmmm_frontier_openmm.py` (OpenMM-gated), and the pure redistribution
math (including a finite-difference gradient check) in
`tests/test_qmmm_frontier.py`.
37 changes: 0 additions & 37 deletions examples/QMMM/ala-dipeptide_BHHLYP-QMMM-MD-RCD.inp

This file was deleted.

2 changes: 0 additions & 2 deletions pyoqp/oqp/library/namd.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,6 @@ def _resolve_aux(name):
self.cutoff = _resolve_cutoff(str(q['cutoff']).strip()) # NoCutoff | PME | Ewald | ...
self.periodic = self.cutoff is not app.NoCutoff
embedding = str(q['embedding']).strip()
frontier_scheme = str(q.get('frontier_scheme', 'none')).strip()

self.pdb = app.PDBFile(pdb_file)
self.forcefield = app.ForceField(*ff_files)
Expand All @@ -404,7 +403,6 @@ def _resolve_aux(name):
mol=mol,
Cutoff=self.cutoff,
Embedding=embedding,
frontier_scheme=frontier_scheme,
)
self.mm = self.driver.mm_systems

Expand Down
Loading
Loading