PERI: fix per-type-pair critical stretch bond breaking (#984), with cleanup and tests#5011
Conversation
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>
There was a problem hiding this comment.
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
smintoatom_style periand use it to compute per-bond breaking thresholds00[ij] - alpha[ij]*max(smin_i,smin_j)across PERI pair styles and/ompvariants. - PERI cleanup/modernization: remove dead members, fix warning/error text, switch bond-count reporting to
utils::logmesgwithbigint. - Add a self-contained PERI unit test and update PERI documentation and
compute property/atomdocs 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). |
|
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. |
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. |
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
left a comment
There was a problem hiding this comment.
It looks OK to me, but I am no peridynamics expert either.
|
@akohlmey I would also like to review this one before merging |
|
@akohlmey @jtclemm The summary says this is fixing an issue with the PMB PD style, but the change is applied to 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. |
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. 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. |
|
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). |
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*smininto a single per-particle scalar (the maximum ofs00 - alpha*sover a particle's bonds). That is only valid whens00andalphaare identical for all type pairs; with type-dependent coefficients abond inherited the critical stretch of the surrounding bulk bonds, so a
deliberately weakened interface (a smaller
s00on the 1-2 type pair) wouldnever fracture.
The fix stores the geometric minimum stretch in a new per-atom field
atom->sminand evaluates the critical stretch per bond at break time ass00[ij] - alpha[ij]*max(smin_i, smin_j). This equalsmin(s0_i, s0_j)foruniform coefficients (bit-for-bit backward compatible) and honors the
per-type
s00/alphaotherwise. The per-atoms0diagnostic is kept andfilled exactly as before. Applied to
peri/pmb,peri/lps,peri/ves,peri/epsand theperi/pmb/ompandperi/lps/ompaccelerator variants.Commit 2 is an independent PERI-wide cleanup (no functional change to the
existing examples, verified bit-for-bit):
PairPeri::elastic_energy(declared, destroyed andexposed via
extract()but never allocated) andFixPeriNeigh::r1/FixPeriNeigh::thetaValue(declared, never used);compute damage/atom(it warned about"dilatation/atom"),
"Illegal compute Dilatation/atom", and the"wighted"/"instanteneous" comment typos;
utils::logmesgand accumulate thecount as a
bigint(the previousinttotal could overflow for largemodels);
MY_PIinstead of a hardcoded3.141592653589793inperi/epsandperi/ves(bit-identical, matchesperi/lps).peri/epswould allocatethetaonly toatom->nlocalbut it is usedin 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-Bytrailers on the commits).Backward Compatibility
s00/alphathe bond-breaking decisions are bit-for-bitidentical to before (the
peri/pmbshatter example reproduces thereference log exactly), so existing inputs behave unchanged.
s0value reported bycompute property/atom s0keeps itsprevious meaning and values. The documentation for it is corrected: earlier
docs incorrectly described
s0as the maximum bond stretch; it is theper-particle critical stretch.
atom_style perigains a per-atom field (smin), so the binary restartlayout for peri systems changes: restart files written with this version
are not interchangeable with those from older versions. (No data-file format
change;
sminis not written to or read from data files.)Implementation Notes
sminis added as a regular per-atom field (registered inAtom, listed inAtomVecPeri's grow/copy/comm/border/exchange/restart/create field lists)so it migrates with atoms and is ghosted, exactly like
s0. The pair styleskeep a transient
smin_newscratch buffer (mirrorings0_new) because thebreak test reads the previous step's
sminof neighbors while the newvalues are accumulated.
sminis-DBL_MAX(so theimplied critical stretch is
+infinity), which preserves the documented"no bond breaking on the first timestep" behavior; the
+DBL_MAXvalue usedto initialize the per-step MIN accumulator is mapped back to
-DBL_MAXforbondless atoms.
unittest/force-styles/test_pair_peri.cpp(interfacefracture for pmb/lps that fails on the old code, below-threshold no-break,
s0 == s00 - alpha*sminrelation, momentum conservation, base-vs-/ompconsistency, 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