Skip to content

[Code scan] Preserve virtual atom types in dpmodel stat and LMDB utilities #5633

Description

@njzjz

Found during a Codex global scan of deepmodeling/deepmd-kit at commit 73de44b1f94471b2e3bdb6b11f57b34d7bc791bb.

Problem

Several dpmodel statistics and LMDB reader paths treat negative/virtual atom types as real type indices.

Evidence:

  • collect_observed_types() records all unique atom-type values and only filters the upper bound, so -1 passes and becomes type_map[-1]:
    observed_indices: set[int] = set()
    for system in sampled:
    atype = to_numpy_array(system["atype"]) # shape: [nframes, natoms]
    observed_indices.update(np.unique(atype).tolist())
    observed_types = [
    type_map[i] for i in sorted(observed_indices) if i < len(type_map)
    ]
    return sort_element_type(observed_types)
  • LmdbDataReader._compute_natoms_vec() calls np.bincount(atype, ...), which raises when atype contains negative virtual atoms:
    def _compute_natoms_vec(self, atype: np.ndarray) -> np.ndarray:
    """Compute natoms_vec from a frame's atype array.
    Returns [nloc, nloc, count_type0, count_type1, ...] with length ntypes+2.
    """
    nloc = len(atype)
    counts = np.bincount(atype, minlength=self._ntypes)[: self._ntypes]
    vec = np.empty(self._ntypes + 2, dtype=np.int64)
    vec[0] = nloc
    vec[1] = nloc
    vec[2:] = counts
    return vec
  • When an LMDB type map is remapped, the reader indexes self._type_remap[frame["atype"]]; atype == -1 is remapped to the last real model type:
    if "atype" in frame and isinstance(frame["atype"], np.ndarray):
    frame["atype"] = frame["atype"].reshape(-1).astype(np.int64)
    # Remap atom types from LMDB's type_map to model's type_map
    if self._type_remap is not None:
    frame["atype"] = self._type_remap[frame["atype"]].astype(np.int64)

Simple external checks confirm both symptoms: np.bincount(np.array([0, -1])) raises ValueError, while remap[np.array([0, -1, 1])] maps -1 through the last row.

Impact

Datasets containing virtual atoms can crash LMDB reading, report fake observed elements, or silently convert virtual atoms into a real species after type-map remapping.

Suggested Fix

Filter atom types with 0 <= atype < ntypes for statistics and counts, and preserve negative atom types during LMDB type remapping. Add tests with atype=[0, -1, 1] for observed-type collection, natoms-vector computation, and LMDB remapping.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions