Skip to content

PERI: fix per-type-pair critical stretch bond breaking (#984), with cleanup and tests#5011

Merged
akohlmey merged 4 commits into
lammps:developfrom
akohlmey:peri-bugfix-refactor-tests
Jun 17, 2026
Merged

PERI: fix per-type-pair critical stretch bond breaking (#984), with cleanup and tests#5011
akohlmey merged 4 commits into
lammps:developfrom
akohlmey:peri-bugfix-refactor-tests

Conversation

@akohlmey

@akohlmey akohlmey commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

Fixes the per-type-pair critical-stretch bond-breaking criterion in the PERI
package (issue #984), plus a package-wide review with dead-code removal,
typo/error-message fixes, modernization, new unit tests, and documentation
updates.

The PMB-style breaking criterion collapsed the per-bond critical stretch
s0 = s00 - alpha*smin into a single per-particle scalar (the maximum of
s00 - alpha*s over a particle's bonds). That is only valid when s00 and
alpha are identical for all type pairs; with type-dependent coefficients a
bond inherited the critical stretch of the surrounding bulk bonds, so a
deliberately weakened interface (a smaller s00 on the 1-2 type pair) would
never fracture.

The fix stores the geometric minimum stretch in a new per-atom field
atom->smin and evaluates the critical stretch per bond at break time as
s00[ij] - alpha[ij]*max(smin_i, smin_j). This equals min(s0_i, s0_j) for
uniform coefficients (bit-for-bit backward compatible) and honors the
per-type s00/alpha otherwise. The per-atom s0 diagnostic is kept and
filled exactly as before. Applied to peri/pmb, peri/lps, peri/ves,
peri/eps and the peri/pmb/omp and peri/lps/omp accelerator variants.

Commit 2 is an independent PERI-wide cleanup (no functional change to the
existing examples, verified bit-for-bit):

  • remove dead members PairPeri::elastic_energy (declared, destroyed and
    exposed via extract() but never allocated) and FixPeriNeigh::r1 /
    FixPeriNeigh::thetaValue (declared, never used);
  • fix a copy/paste warning in compute damage/atom (it warned about
    "dilatation/atom"), "Illegal compute Dilatation/atom", and the
    "wighted"/"instanteneous" comment typos;
  • modernize the bond-count report to utils::logmesg and accumulate the
    count as a bigint (the previous int total could overflow for large
    models);
  • use MY_PI instead of a hardcoded 3.141592653589793 in peri/eps and
    peri/ves (bit-identical, matches peri/lps).
  • peri/eps would allocate theta only to atom->nlocal but it is used
    in a forward communication to store it with ghost atoms. allocate to atom->nmax

Related Issue(s)

Fixes #984

Author(s)

Axel Kohlmeyer (Temple University), akohlmey@gmail.com

Licensing

By submitting this pull request, I agree, that my contribution will be
included in LAMMPS and redistributed under either the GNU General Public
License version 2 (GPL v2) or the GNU Lesser General Public License version
2.1 (LGPL v2.1).

Artificial Intelligence (AI) Tools Usage

These changes were developed with the assistance of an AI tool (Claude Code,
model Claude Opus) used interactively under the direction and review of the
author. The AI assisted with the root-cause analysis, the implementation of
the bond-breaking fix across the pair styles and atom-style plumbing, the new
unit test, the documentation edits, and the dead-code/typo cleanup. All
changes were reviewed, tested, and verified by the author before submission
(consistent with the Co-Authored-By trailers on the commits).

Backward Compatibility

  • For uniform s00/alpha the bond-breaking decisions are bit-for-bit
    identical to before (the peri/pmb shatter example reproduces the
    reference log exactly), so existing inputs behave unchanged.
  • The per-atom s0 value reported by compute property/atom s0 keeps its
    previous meaning and values. The documentation for it is corrected: earlier
    docs incorrectly described s0 as the maximum bond stretch; it is the
    per-particle critical stretch.
  • atom_style peri gains a per-atom field (smin), so the binary restart
    layout for peri systems changes: restart files written with this version
    are not interchangeable with those from older versions. (No data-file format
    change; smin is not written to or read from data files.)

Implementation Notes

  • smin is added as a regular per-atom field (registered in Atom, listed in
    AtomVecPeri's grow/copy/comm/border/exchange/restart/create field lists)
    so it migrates with atoms and is ghosted, exactly like s0. The pair styles
    keep a transient smin_new scratch buffer (mirroring s0_new) because the
    break test reads the previous step's smin of neighbors while the new
    values are accumulated.
  • The "no bonds / first compute" sentinel for smin is -DBL_MAX (so the
    implied critical stretch is +infinity), which preserves the documented
    "no bond breaking on the first timestep" behavior; the +DBL_MAX value used
    to initialize the per-step MIN accumulator is mapped back to -DBL_MAX for
    bondless atoms.
  • Verification: new unittest/force-styles/test_pair_peri.cpp (interface
    fracture for pmb/lps that fails on the old code, below-threshold no-break,
    s0 == s00 - alpha*smin relation, momentum conservation, base-vs-/omp
    consistency, and a /kk-ready case that skips until a KOKKOS port exists);
    all four examples reproduce their reference logs for the bond-based case and
    are otherwise unchanged; make check (whitespace/permissions) is clean.

Post Submission Checklist

  • The feature or features in this pull request is complete
  • Licensing information is complete
  • Corresponding author information is complete
  • The source code follows the LAMMPS formatting guidelines
  • Suitable new documentation files and/or updates to the existing docs are included
  • The added/updated documentation is integrated and tested with the documentation build system
  • The feature has been verified to work with the conventional build system
  • The feature has been verified to work with the CMake based build system
  • Suitable tests have been added to the unittest tree.
  • A package specific README file has been included or updated
  • One or more example input decks are included

akohlmey and others added 2 commits June 2, 2026 23:09
The PMB-style bond-breaking criterion collapsed the per-bond critical
stretch s0 = s00 - alpha*smin into a single per-particle scalar (the max
over the particle's bonds). That is only valid when s00 and alpha are
identical for all type pairs; with type-dependent coefficients a bond
inherited the critical stretch of the surrounding bulk bonds, so a
deliberately weakened interface (smaller s00 on the 1-2 type pair) would
never fracture.

Store the geometric minimum stretch in a new per-atom field atom->smin and
evaluate the critical stretch per bond at break time as
s00[ij] - alpha[ij]*max(smin_i,smin_j), which equals min(s0_i,s0_j) for
uniform coefficients (bit-for-bit backward compatible) and honors the
per-type s00/alpha otherwise. s0 is kept, filled exactly as before, as a
per-particle diagnostic only. Applied to peri/pmb, peri/lps, peri/ves,
peri/eps and the pmb/lps OPENMP variants.

Also:
- add unittest/force-styles/test_pair_peri.cpp (base + /omp + /kk-ready)
- document the criterion in pair_peri.rst (+ versionchanged) and correct
  the s0 description in compute_property_atom.rst
- remove the never-allocated vestigial PairPeri::elastic_energy member

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review of the PERI package found:

- remove dead members FixPeriNeigh::r1 and FixPeriNeigh::thetaValue
  (declared but never allocated or used)
- fix copy/paste warning text in compute damage/atom (it said
  "dilatation/atom"), "Illegal compute Dilatation/atom" -> "dilatation",
  and the "wighted"/"instanteneous" comment typos
- modernize the bond-count report to utils::logmesg and accumulate the
  count as a bigint (the previous int total could overflow for large models)
- use MY_PI instead of a hardcoded 3.141592653589793 in peri/eps and
  peri/ves (bit-identical, matches peri/lps)
- Howto_peri.rst: describe the per-bond critical-stretch evaluation in the
  "Breaking Bonds" section (+ versionchanged)

No functional change to the existing examples (verified bit-for-bit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@akohlmey akohlmey self-assigned this Jun 3, 2026
@akohlmey akohlmey moved this to Ready for Review or Merge in LAMMPS Pull Requests Jun 3, 2026
@akohlmey akohlmey added this to the Feature Release June 2026 milestone Jun 3, 2026
@akohlmey
akohlmey marked this pull request as ready for review June 3, 2026 08:20
@akohlmey
akohlmey requested a review from sjplimp as a code owner June 3, 2026 08:20
@akohlmey
akohlmey requested a review from Copilot June 3, 2026 08:21
@akohlmey
akohlmey requested review from athomps and jtclemm June 3, 2026 08:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes PERI’s bond-breaking criterion for per-type-pair s00/alpha (issue #984) by introducing a new per-atom smin field and evaluating the critical stretch per bond at break time, while also cleaning up unused PERI code paths and adding a dedicated unit test plus documentation updates.

Changes:

  • Add per-atom smin to atom_style peri and use it to compute per-bond breaking threshold s00[ij] - alpha[ij]*max(smin_i,smin_j) across PERI pair styles and /omp variants.
  • PERI cleanup/modernization: remove dead members, fix warning/error text, switch bond-count reporting to utils::logmesg with bigint.
  • Add a self-contained PERI unit test and update PERI documentation and compute property/atom docs for the corrected meaning/behavior.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
unittest/force-styles/test_pair_peri.cpp New self-contained PERI regression/invariant tests for bond breaking and accelerator consistency.
unittest/force-styles/CMakeLists.txt Adds test_pair_peri executable/test when PKG_PERI is enabled.
src/PERI/pair_peri.h Adds smin_new scratch storage; removes unused elastic_energy member.
src/PERI/pair_peri.cpp Initializes/destroys smin_new; removes elastic_energy extraction path.
src/PERI/pair_peri_ves.cpp Implements per-bond breaking using smin; replaces hardcoded π with MathConst::MY_PI; allocates smin_new.
src/PERI/pair_peri_pmb.cpp Implements per-bond breaking using smin; allocates and stores smin.
src/PERI/pair_peri_lps.cpp Implements per-bond breaking using smin; typo fix in comment; allocates and stores smin.
src/PERI/pair_peri_eps.cpp Implements per-bond breaking using smin; uses MY_PI; allocates and stores smin.
src/PERI/fix_peri_neigh.h Removes unused r1 and thetaValue members.
src/PERI/fix_peri_neigh.cpp Switches bond statistics logging to utils::logmesg and uses bigint + MPI_LMP_BIGINT.
src/PERI/compute_dilatation_atom.cpp Fixes error message capitalization to match style name.
src/PERI/compute_damage_atom.cpp Fixes copy/paste warning message to reference damage/atom.
src/PERI/atom_vec_peri.h Adds smin pointer to AtomVecPeri’s private cached pointers.
src/PERI/atom_vec_peri.cpp Registers/communicates/initializes new per-atom smin field (incl. restart/exchange).
src/OPENMP/pair_peri_pmb_omp.cpp Applies the same smin-based per-bond breaking logic in the OMP variant.
src/OPENMP/pair_peri_lps_omp.cpp Applies the same smin-based per-bond breaking logic in the OMP variant.
src/atom.h Adds smin to PERI per-atom fields in Atom.
src/atom.cpp Registers smin via add_peratom() and initializes pointer to nullptr.
doc/src/pair_peri.rst Documents the corrected bond-breaking criterion and corrects s0 description; adds .. versionchanged:: TBD.
doc/src/Howto_peri.rst Updates algorithm narrative to reflect storing smin and per-bond evaluation; adds .. versionchanged:: TBD.
doc/src/compute_property_atom.rst Corrects PERI s0 property description (critical stretch threshold, not max bond stretch).

Comment thread src/PERI/pair_peri_eps.cpp Outdated
Comment thread unittest/force-styles/test_pair_peri.cpp Outdated
@jtclemm

jtclemm commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Cleaning up PERI is a good task, but I believe an even better solution is to just port the force models to bond styles via the BPM package and scrap the existing code. This is something that's has been floated to be done this summer.

If I recall correctly, the PERI package hard codes both the solid mechanics + contact models into a single pair style so users can't mix and match. Tying the solid models to a pair style also prohibits control over the solid geometry. The pair styles automatically create pseudo-bonds from the initial neighbor list so users can't create cracks, place solid objects adjacent to each other, output connectivity, etc.

The schema in the BPM package is more flexible and works with other LAMMPS commands since it just uses actual bonds. Using a single framework for both packages would also remove a lot of cryptic code for fitting the solid models in a pair style (PERI pair styles can just be children of BondBPM which includes all the needed infrastructure).

I can review these changes and we can merge them, but they may ultimately be a stop gap.

@akohlmey

akohlmey commented Jun 3, 2026

Copy link
Copy Markdown
Member Author

I can review these changes and we can merge them, but they may ultimately be a stop gap.

I am fine with this. I only would suggest that when this gets superseded by BPM we need a "porting guide" added to the Peridynamics Howto and then add a statement in the docs and a warning in the implementation that we discourage the use of the PERI package and will eventually remove it (~ 1-2 years later). Same as we did with other, similar cases.

One more piece of advice. Don't treat any of the pull requests that I created with AI support the same way as if I wrote all the changes myself. The way they come to be requires comparatively little effort from me (I need to be very careful when writing the prompt and typically have to make some adjustments to the AI suggested plan and some polishing afterwards) and thus won't be bothered by dropping such a pull request (unlike those where I spent a lot of work on), or parts of it. Ideally, if you can provide some additional guidance, I can use that (and still open or already closed pull request) to repeat the programming task and give it another try. Also, for any issue that has been unresolved for a long time, even a partial fix is preferable over doing nothing. Or when the proposed change should be dropped we should change the documentation and explain.

As I get more practice and for as long as I have sufficient access to a frontier model, there should be improvements when re-doing a such fixes, since I am asking to record my personal feedback on suggested solutions.

akohlmey added a commit that referenced this pull request Jun 5, 2026
The critical stretch threshold for bond breaking was collapsed to a
single per-particle scalar via MAX(s00-alpha*stretch), which gave a
wrong result when different atom-type pairs have different s00 or alpha
parameters.

Fix (Option A, backward-compatible): repurpose atom->s0 to store the
minimum stretch over all surviving bonds of a particle.  The bond-
breaking criterion is now evaluated per bond as:

  crit_ij = s00[i][j] - alpha[i][j] * MAX(s0[i], s0[j])

where s0[i] is the minimum stretch from the previous timestep.  Using
MAX(s0_i, s0_j) means a particle with many small stretches cannot shield
a bond that exceeds the threshold from the other side.  Atoms with no
surviving bonds carry the sentinel -DBL_MAX so they cannot spuriously
trigger bond breaking in their neighbors.

Also remove the never-allocated `elastic_energy` dead member from the
PairPeri base class.

Applies changes from PR #5011 (upstream commit c6e8014) in a form
that avoids adding a new per-atom field and preserving restart
compatibility, at the cost of losing the old (incorrect) s0 meaning.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@stanmoore1 stanmoore1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It looks OK to me, but I am no peridynamics expert either.

@sjplimp

sjplimp commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

@akohlmey I would also like to review this one before merging

@sjplimp sjplimp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

still want to review

@sjplimp

sjplimp commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

@akohlmey @jtclemm The summary says this is fixing an issue with the PMB PD style, but the change is applied to
multiple PD styles. Possibly all 4 of them, though the code for EPS looks a bit different. Are we confident that is the correct thing to do?

One of these 4 styles should be the original PD implementation in LAMMPS, possibly PMB, but not sure since we later changed the names as more variants were added. The original PD was implemented with help from Mike Parks who was part of the PD group at Sandia. So I would be surprised if the bond-breaking criteria in that version was incorrect or incomplete. Unless it was a later refinement in PD itself (completely independent of LAMMPS), which the LAMMPS version never caught up with.

@akohlmey

Copy link
Copy Markdown
Member Author

The summary says this is fixing an issue with the PMB PD style, but the change is applied to multiple PD styles. Possibly all 4 of them, though the code for EPS looks a bit different. Are we confident that is the correct thing to do?

This pull request started as a bugfix for issue #984, but upon closer inspection, the issue was present in all peri variants. For peri/eps I also discovered a memory allocation bug: the theta array was used for forward communication but only allocated to atom->nlocal.
As mentioned in the description for the ceramic disk example, the fix here does not make a difference.

There is a bit of a risk, but on the other hand the code before this pull request is definitely incorrect. We will get a thorough check when @jtclemm's plan's to recast the PERI package into the BPM framework will happen.

@sjplimp

sjplimp commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

ok - I will approve it - I support the @jtclemm plan to support PD within BPM if that can be done staightforwardly, since it is actively developed. It would also be nice to know if BPM/PD is as performant as the current PD, since it is a fairly simple model (at least the original PD in LAMMPS).

@akohlmey
akohlmey merged commit 3bfc12b into lammps:develop Jun 17, 2026
9 checks passed
@github-project-automation github-project-automation Bot moved this from Ready for Review or Merge to Done in LAMMPS Pull Requests Jun 17, 2026
@akohlmey
akohlmey deleted the peri-bugfix-refactor-tests branch June 17, 2026 02:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

[BUG] Problem with critical strain s0 in pair_style peri/pmb

5 participants