Skip to content

feat(lammps): generate masses for lammps/lmp export#963

Open
njzjz-bot wants to merge 3 commits intodeepmodeling:masterfrom
njzjz-bothub:feat/lammps-lmp-generate-masses
Open

feat(lammps): generate masses for lammps/lmp export#963
njzjz-bot wants to merge 3 commits intodeepmodeling:masterfrom
njzjz-bothub:feat/lammps-lmp-generate-masses

Conversation

@njzjz-bot
Copy link
Copy Markdown
Contributor

@njzjz-bot njzjz-bot commented Mar 31, 2026

Problem

  • lammps/lmp export currently does not emit a Masses section.
  • For systems whose atom_names are known element symbols, the masses can be generated safely.

Change

  • prefer explicitly stored masses data when present
  • otherwise infer per-type masses from atom_names when all names are valid element symbols
  • keep the previous behavior for unknown type names and add regression tests for both paths
  • make the new regression tests independent of the current working directory

Closes #960

Authored by OpenClaw (model: custom-chat-jinzhezeng-group/gpt-5.4)

Summary by CodeRabbit

  • New Features

    • LAMMPS output now includes a Masses section (with per-type masses and atom-name comments) when masses can be provided or safely inferred; placed between the header/box and atom coordinate blocks.
  • Tests

    • Added tests verifying Masses are written for known elements, omitted when types/masses cannot be determined, and that mismatched explicit masses raise an error.

Prefer explicitly stored masses when available, and otherwise infer
per-type masses from atom_names when all names are valid element
symbols. Keep the previous behavior for unknown type names so exports
do not emit unsafe Masses sections.

Add regression tests covering both known-element and unknown-type cases,
and make the new tests independent of the current working directory.

Authored by OpenClaw (model: custom-chat-jinzhezeng-group/gpt-5.4)
@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. enhancement New feature or request lammps labels Mar 31, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 31, 2026

Merging this PR will not alter performance

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

✅ 2 untouched benchmarks


Comparing njzjz-bothub:feat/lammps-lmp-generate-masses (9e33657) with master (1e79653)

Open in CodSpeed

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

❌ Patch coverage is 95.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 86.70%. Comparing base (1e79653) to head (9e33657).

Files with missing lines Patch % Lines
dpdata/lammps/lmp.py 95.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #963      +/-   ##
==========================================
+ Coverage   86.65%   86.70%   +0.04%     
==========================================
  Files          86       86              
  Lines        8019     8039      +20     
==========================================
+ Hits         6949     6970      +21     
+ Misses       1070     1069       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Run repository pre-commit hooks and keep the ruff import ordering fix.

Authored by OpenClaw (model: custom-chat-jinzhezeng-group/gpt-5.4)
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a9fedf1c-1a27-4e3c-bcb9-50923f8d5fef

📥 Commits

Reviewing files that changed from the base of the PR and between 6d6dcda and 9e33657.

📒 Files selected for processing (2)
  • dpdata/lammps/lmp.py
  • tests/test_lammps_lmp_dump.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_lammps_lmp_dump.py

📝 Walkthrough

Walkthrough

Add LAMMPS mass generation: new helper _get_lammps_masses(system) derives per-type masses (from system["masses"] or by inferring element symbols) and from_system_data() emits a Masses block before the Atoms # atomic section when masses are available.

Changes

Cohort / File(s) Summary
LAMMPS mass generation
dpdata/lammps/lmp.py
Added `_get_lammps_masses(system) -> np.ndarray
Tests for mass output
tests/test_lammps_lmp_dump.py
Added TEST_DIR and POSCAR_CONF_LMP constants and new TestLmpDumpMasses with three tests: writing masses when types known, skipping masses when types unknown, and rejecting mismatched explicit masses length (raises ValueError).

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(lammps): generate masses for lammps/lmp export' directly and clearly summarizes the main change: adding mass generation capability to the LAMMPS/LMP exporter.
Linked Issues check ✅ Passed The pull request fully implements the objective from issue #960 to generate masses for lammps/lmp exports, including handling of known elements, explicit masses, and validation logic.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the stated objectives: the new helper function generates masses, updated export logic conditionally emits the Masses section, and tests validate the behavior across three scenarios without unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dpdata/lammps/lmp.py`:
- Around line 553-554: The loop that pairs masses and atom names uses
zip(masses, system["atom_names"]) which can silently truncate mismatched
lengths; update the zip call to zip(masses, system["atom_names"], strict=True)
in the code that builds ret (the loop using enumerate over (mass, atom_name) and
mass_fmt) so Python will raise on length mismatches and avoid silent bugs.
- Around line 508-509: The current logic slices a provided masses list to
atom_names length which can silently mis-map types; in the function handling
system["masses"] (the variables masses and atom_names in lmp.py) change the
check to require exact length equality (len(masses) == len(atom_names)) and
otherwise return None or raise a clear ValueError instead of truncating; update
the branch that currently does "if masses is not None and len(masses) >=
len(atom_names): return np.asarray(masses[: len(atom_names)], ...)" to only
accept exact matches and ensure any downstream code that emits Masses handles
the None/error case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 35a43b4e-3052-494f-a9a9-070032699387

📥 Commits

Reviewing files that changed from the base of the PR and between 1e79653 and 58c4bb6.

📒 Files selected for processing (2)
  • dpdata/lammps/lmp.py
  • tests/test_lammps_lmp_dump.py

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
dpdata/lammps/lmp.py (2)

506-509: ⚠️ Potential issue | 🟠 Major

Require exact length match for explicit masses to avoid silent mis-mapping.

The current logic len(masses) >= len(atom_names) with slicing can silently truncate when more masses than types are provided, potentially assigning wrong masses to types. This was flagged in a previous review and should require exact equality.

Proposed fix
     atom_names = system["atom_names"]
     masses = system.get("masses")
-    if masses is not None and len(masses) >= len(atom_names):
-        return np.asarray(masses[: len(atom_names)], dtype=float)
+    if masses is not None:
+        masses = np.asarray(masses, dtype=float)
+        if masses.ndim == 1 and len(masses) == len(atom_names):
+            return masses
+        # Mismatched shape/length: fall through to element inference or return None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dpdata/lammps/lmp.py` around lines 506 - 509, The code currently allows more
masses than atom types and silently truncates via slicing; update the check in
the block that reads atom_names and masses (variables atom_names and masses in
this module/function) to require exact length equality (use len(masses) ==
len(atom_names)); if they differ, raise a clear ValueError (or similar)
indicating the mismatch between provided masses and atom_names instead of
slicing, otherwise return the masses converted to float with np.asarray(masses,
dtype=float).

553-554: ⚠️ Potential issue | 🟡 Minor

Add strict=True to zip() to satisfy Ruff B905 and guard against length mismatches.

The zip() call is missing the strict= parameter, which is flagged by Ruff (B905). Adding strict=True ensures a runtime error if masses and atom_names have mismatched lengths.

Proposed fix
-        for ii, (mass, atom_name) in enumerate(zip(masses, system["atom_names"])):
+        for ii, (mass, atom_name) in enumerate(
+            zip(masses, system["atom_names"], strict=True)
+        ):

As per coding guidelines: "Run ruff linting with ruff check dpdata/".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dpdata/lammps/lmp.py` around lines 553 - 554, Update the zip call in the loop
that builds `ret` so it uses strict=True to enforce equal lengths: change the
`for ii, (mass, atom_name) in enumerate(zip(masses, system["atom_names"])):`
loop in `dpdata/lammps/lmp.py` to pass strict=True to zip (i.e.,
enumerate(zip(masses, system["atom_names"], strict=True))) so mismatched lengths
raise at runtime; ensure no other logic relies on silent truncation of `masses`
vs `system["atom_names"]`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@dpdata/lammps/lmp.py`:
- Around line 506-509: The code currently allows more masses than atom types and
silently truncates via slicing; update the check in the block that reads
atom_names and masses (variables atom_names and masses in this module/function)
to require exact length equality (use len(masses) == len(atom_names)); if they
differ, raise a clear ValueError (or similar) indicating the mismatch between
provided masses and atom_names instead of slicing, otherwise return the masses
converted to float with np.asarray(masses, dtype=float).
- Around line 553-554: Update the zip call in the loop that builds `ret` so it
uses strict=True to enforce equal lengths: change the `for ii, (mass, atom_name)
in enumerate(zip(masses, system["atom_names"])):` loop in `dpdata/lammps/lmp.py`
to pass strict=True to zip (i.e., enumerate(zip(masses, system["atom_names"],
strict=True))) so mismatched lengths raise at runtime; ensure no other logic
relies on silent truncation of `masses` vs `system["atom_names"]`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6eb2e3bf-b985-4573-ad43-3d7dbed897af

📥 Commits

Reviewing files that changed from the base of the PR and between 58c4bb6 and 6d6dcda.

📒 Files selected for processing (1)
  • dpdata/lammps/lmp.py

Reject explicit system["masses"] arrays unless they match atom_names exactly to avoid silently truncating and mis-mapping LAMMPS Masses entries. Add a regression test covering the mismatched-length case.

Authored by OpenClaw (model: custom-chat-jinzhezeng-group/gpt-5.4)
@njzjz njzjz requested a review from wanghan-iapcm March 31, 2026 04:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request lammps size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] lammps/lmp: Generate mass

2 participants