GRANULAR: fix energy injection in fix wall/gran hooke/history at grazing impacts#5007
Conversation
`fix wall/gran hooke/history` (and the equivalent classic tangential model selected via `define_classic_model`) could *gain* kinetic energy on a grazing oblique impact with friction -- up to +34% at mu=0.5, ~76 deg from normal -- with the rebound tangential speed exceeding the incoming one. The gain is real (converges as dt -> 0), grows with mu and impact angle, and is absent for mu=0. Root cause: `GranSubModTangentialLinearHistoryClassic` set `contact_radius_flag = 1`, so the tangential elastic force was scaled by the overlap-dependent contact radius (kt * sqrt(delta*R) for a Hooke contact). That makes the tangential spring stiffness vary within a single contact, which is non-conservative and pumps energy when the contact normal rotates quickly. The original standalone pair gran/hooke/history and the modern `linear_history` model both use a constant tangential stiffness kt. Only the Hertzian variant (`mindlin_classic`, gran/hertz/history) should scale the tangential stiffness by the contact radius, and it sets the flag itself. Fix: set `contact_radius_flag = 0` in the `linear_history_classic` constructor (Hooke). With this, fix wall/gran hooke/history dissipates across the whole angle range and matches the modern `linear_history` result exactly (grazing KE ratio 1.342 -> 0.727); gran/hertz/history and the frictionless case are unchanged. Note: this changes the *frictional* behavior of fix wall/gran hooke/history, which previously used the (incorrect, overlap-scaled) tangential stiffness; the tangential force is now the documented constant kt. The standalone pair gran/hooke/history is a separate class and is unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a versionchanged note to fix_wall_gran.rst documenting that the hooke/history wall model now uses a constant tangential stiffness Kt (matching pair_style gran/hooke/history), instead of the previous overlap-dependent, non-conservative scaling that could inject energy on grazing impacts. Also records that the KOKKOS variant (wall/gran/kk) was already using the constant-stiffness form: it derives from the internal WALL/GRAN/OLD class (src/KOKKOS/fix_wall_gran_old) whose device kernel computes the tangential force as -(kt*history + meff*gammat*vtr) with no contact-radius factor, and it only supports hooke/history. The KOKKOS version therefore needs no change; this fix instead brings the modern CPU fix wall/gran into agreement with it and with the standalone pair style. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
I believe this bug fix is indeed correct. I probably forgot to swap the flag for Hooke when porting the old classic implementation into the new granular model format. However, I think we could just make the 1 line change. The old/classic styles have several known physical issues with them anyway and shouldn't really be used. We should probably think about deprecating them. |
Please note that the full content of this branch is also included in #5008 My suggestion would thus be: merge this as is (or merge #5008 and close this if not automatically closed) and the have a new PR that prints deprecation warnings and removes/updates the note from the docs accordingly. |
jtclemm
left a comment
There was a problem hiding this comment.
Not sure if this needs to be approved separately from the unit tests.
Summary
fix wall/gran hooke/historycould gain kinetic energy on a grazing oblique impact with friction (up to +34% atmu=0.5, ~76 deg from the wall normal), with the rebound tangential speed exceeding the incoming one. This one-line change corrects the underlying classic tangential model so the wall dissipates energy at all impact angles, matching the result of the modernpair_style granular(linear_history) model, the standalonepair_style gran/hooke/history, and the KOKKOSfix wall/gran/kk.Related Issue(s)
None. Found while developing a YAML-driven granular/DEM regression test suite.
Author(s)
Axel Kohlmeyer (LAMMPS Development Team)
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
This change was developed with the assistance of Claude Code (Anthropic, Claude Opus). The AI tool was used to investigate and characterize the energy-injection behavior and to draft the code change, the explanatory comment, and the documentation note; the diagnosis and the changes were reviewed by a human. This is consistent with the
Co-Authored-Bytrailer on the commits.Backward Compatibility
Yes. This changes the frictional behavior of
fix wall/gran hooke/history. Previously the classic tangential model (GranSubModTangentialLinearHistoryClassic) setcontact_radius_flag = 1, scaling the tangential elastic force by the overlap-dependent contact radiussqrt(delta*R). That makes the effective tangential stiffness both much smaller than the nominalktand time-varying within a contact (non-conservative). After this change the tangential stiffness is the constantkt, as in the original standalonepair_style gran/hooke/historyand the modernlinear_historymodel. Simulations usingfix wall/gran hooke/historywith non-zero friction will therefore produce different (corrected) trajectories. The frictionless case,fix wall/gran hertz/history, and the standalonepair_style gran/*styles are unaffected. A.. versionchanged:: TBDnote documenting this is included indoc/src/fix_wall_gran.rst.Implementation Notes
Root cause:
define_classic_modelmaps thehooke/historykeyword to a Hooke normal model plus theGranSubModTangentialLinearHistoryClassictangential model, whose constructor setcontact_radius_flag = 1. For a Hooke contactcontact_radius = sqrt(delta*R)varies during the contact, so the tangential elastic force-kt * contact_radius * historyhas a time-varying stiffness. This is non-conservative and pumps kinetic energy when the contact normal rotates quickly within a single contact, i.e. on grazing oblique impacts. The originalpair_style gran/hooke/historyand the modernlinear_historyboth use a constantkt; only the Hertzian variant (mindlin_classic, used byhertz/history) should scale the tangential stiffness by the contact radius, and it sets the flag in its own constructor.Fix: set
contact_radius_flag = 0in theGranSubModTangentialLinearHistoryClassicconstructor.KOKKOS: the KOKKOS variant
fix wall/gran/kkdoes not need this change. It derives from the internalWALL/GRAN/OLDclass (src/KOKKOS/fix_wall_gran_old), and its device kernel computes the tangential force as-(kt*history + meff*gammat*vtr)with no contact-radius factor, so it already uses the constant-stiffness (conservative) form and only supportshooke/history. This change brings the modern CPUfix wall/graninto agreement with the KOKKOS path.Verification (single sphere onto a
zplanewall, no gravity, ratio of post- to pre-collision total kinetic+rotational energy; converged with decreasing timestep):linear_history)No existing force-style regression YAML uses this model.
Post Submission Checklist