Skip to content

Anisotropic friction#210

Open
antoinebou12 wants to merge 26 commits intoipc-sim:mainfrom
antoinebou12:anisotropic_friction
Open

Anisotropic friction#210
antoinebou12 wants to merge 26 commits intoipc-sim:mainfrom
antoinebou12:anisotropic_friction

Conversation

@antoinebou12
Copy link
Contributor

Description

This PR adds anisotropic friction support to IPC Toolkit’s tangential contact model, including full derivative support (energy/gradient/Hessian, friction force, and force Jacobians) with backward-compatible defaults.

Summary of changes

  • Per-collision anisotropy parameters

    • Added mu_aniso (tangent-space velocity scaling) and optional direction-dependent ellipse axes mu_s_aniso / mu_k_aniso on TangentialCollision.
    • Defaults preserve existing behavior: mu_aniso = (1,1) and mu_s_aniso = mu_k_aniso = (0,0) (isotropic fallback).
  • Core friction model updates (high impact area)

    • Updated the tangential potential and friction computations to use anisotropically-scaled tangential velocity (tau_aniso).
    • When anisotropic ellipse axes are provided, computes an effective mu_s / mu_k from the (scaled) direction using an elliptical L2 / matchstick formulation; otherwise uses scalar mu_s / mu_k.
    • Updated friction force and force Jacobians to include the derivative of the effective-μ where applicable.
  • New friction helpers

    • Added C++ helpers for effective-μ evaluation and derivatives (e.g., anisotropic_mu_eff_f, anisotropic_mu_eff_f_dtau, anisotropic_mu_eff_from_tau_aniso, etc.).
    • Exposed key helpers + new collision parameters through the Python bindings.
  • Tests

    • Added extensive unit tests for effective-μ math, stability edge cases, and force/Jacobian correctness.
  • Docs

    • Expanded friction docs/tutorials with anisotropic usage examples.
    • Added a derivation/plots notebook and a reference citation for the matchstick model.

Motivation & context

Real materials often exhibit direction-dependent friction (wood grain, brushed/rolled metal, textiles). This PR adds a practical anisotropic model that:

  • Works per-contact (no mesh-wide hacks),
  • Keeps isotropic behavior unchanged by default,
  • Provides consistent derivatives required by optimization/implicit methods.

Dependencies required

  • No new runtime dependencies for the library.
  • Optional (dev/docs only): Jupyter environment to run notebooks/anisotropic_friction_math.ipynb (if you want to reproduce the derivations/plots).

Fixes #4


Type of change

  • Enhancement (non-breaking change which improves existing functionality)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

  • Local CMake build on Windows
  • Unit tests via CTest (including new friction/anisotropy test targets)

Reproduction steps

# configure
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release

# build
cmake --build build --config Release

# run all tests
ctest --test-dir build -C Release

# (optional) focus on friction-related tests
ctest --test-dir build -C Release -R friction

Test Configuration:

  • OS and Version: Windows 11
  • CPU: AMD Ryzen 5
  • GPU: NVIDIA RTX 2080 Ti
  • Compiler and Version: MSVC (Visual Studio 2022 toolchain)

Checklist

  • I have followed the project style guide
  • My code follows the clang-format style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules (N/A — no downstream dependency changes required)

Note

High Risk
Touches core friction force/Jacobian/Hessian code paths used by solvers, so mistakes can affect stability and convergence across simulations. While defaults are backward-compatible and tests were added, the new derivative logic increases numerical/edge-case risk.

Overview
Adds anisotropic friction support to tangential contact by introducing per-collision parameters mu_aniso (tangent-space velocity scaling) and optional direction-dependent ellipse axes mu_s_aniso/mu_k_aniso, with zero/default values preserving existing isotropic behavior.

Updates tangential friction energy/force/gradient/Hessian and force Jacobians to evaluate friction using scaled tangential velocity (tau_aniso) and, when ellipse axes are provided, an effective friction coefficient via an elliptical L2 ("matchstick") model; includes new helper functions (and Python bindings) for effective-μ evaluation and derivatives.

Extends documentation (C++/Python API pages and advanced_friction tutorial), adds the Erleben2019Matchstick reference plus a derivation notebook, and adds/updates unit tests covering the new helpers and anisotropic force/Jacobian correctness.

antoinebou12 and others added 17 commits January 26, 2026 17:31
This commit introduces a new example script demonstrating the use of anisotropic friction in the IPC Toolkit. The script showcases the setup of a simple collision scenario, building normal and tangential collisions, assigning anisotropic friction coefficients, and computing effective friction for various velocity directions. Additionally, it compares the results with isotropic friction to highlight the differences in behavior.
… of effective friction coefficients and ensure finite results. Update documentation to reflect changes in function name and return values.
…nd improve clarity. Update documentation and tests to reflect changes from `anisotropic_mu_eff_sqrt_mu0_t0_sq_plus_mu1_t1_sq` to `anisotropic_mu_eff_f` and related functions.
…ility by consolidating function calls into single lines. This change enhances clarity without altering the test logic.
… and consistency. Convert markdown cells to code cells in the notebook, enhance symbolic variable definitions, and streamline friction force visualization. Update test cases to ensure consistent function calls and improve readability.
…move backward compatibility section from the tutorial, update execution counts in the notebook, and streamline function definitions in the C++ code. Enhance test cases for consistency and readability.
This commit introduces the Matchstick model for anisotropic friction, enhancing the IPC Toolkit's capabilities. Key changes include:

- Addition of the Matchstick model reference in `references.bib`.
- Updates to the C++ and Python API documentation to include anisotropic friction helpers and their usage.
- Enhancements in the `advanced_friction` tutorial to cover anisotropic friction features and their implementation.
- New tests for anisotropic friction transitions and effective coefficient calculations.

Documentation now references Erleben et al. (2019) for the model's derivation and implementation details.
…prove code comments for clarity in tangential collision and potential implementations.
@codecov
Copy link

codecov bot commented Feb 4, 2026

Codecov Report

❌ Patch coverage is 91.01796% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.92%. Comparing base (893dbf2) to head (4ff3dc2).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/ipc/potentials/tangential_potential.cpp 88.03% 14 Missing ⚠️
src/ipc/friction/smooth_mu.cpp 98.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #210      +/-   ##
==========================================
- Coverage   96.96%   96.92%   -0.05%     
==========================================
  Files         161      161              
  Lines       24747    24878     +131     
  Branches      893      908      +15     
==========================================
+ Hits        23997    24114     +117     
- Misses        750      764      +14     
Flag Coverage Δ
unittests 96.92% <91.01%> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

@zfergus
Copy link
Member

zfergus commented Feb 4, 2026

Woooow! This is really awesome. Thanks for the contribution. The matchstick method for anisotropic friction was something I was interested in implementing, so I am super excited you did it already. 😄

I'll review the changes in depth when I have some free time. 🚀

@zfergus zfergus added the enhancement New feature or request label Feb 4, 2026
@zfergus zfergus added this to the v1.6.0 milestone Feb 4, 2026
Copy link
Contributor

Copilot AI left a comment

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 adds anisotropic friction support to IPC Toolkit’s tangential contact model by introducing per-collision anisotropy parameters, helper math for effective direction-dependent friction coefficients, Python bindings, and expanded docs/tests.

Changes:

  • Added anisotropic friction parameters on TangentialCollision (mu_aniso, mu_s_aniso, mu_k_aniso) and exposed them to Python.
  • Updated tangential friction potential/force/Jacobian computations to use anisotropically scaled tangential velocity and effective-μ helpers.
  • Added anisotropic effective-μ helper functions plus new/updated unit tests and documentation.

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
src/ipc/potentials/tangential_potential.cpp Integrates anisotropic scaling/effective-μ into friction potential and force/Jacobian computations.
src/ipc/friction/smooth_mu.hpp Declares new anisotropic effective-μ helpers and derivatives.
src/ipc/friction/smooth_mu.cpp Implements effective-μ evaluation and derivative helpers.
src/ipc/collisions/tangential/tangential_collision.hpp Adds per-collision anisotropy parameters to the tangential collision model.
python/src/friction/smooth_mu.cpp Exposes anisotropic effective-μ helpers to Python.
python/src/collisions/tangential/tangential_collision.cpp Exposes new tangential collision anisotropy fields to Python.
tests/src/tests/potential/test_friction_potential.cpp Updates friction potential FD tests to handle filtered meshes/displacement mapping.
tests/src/tests/friction/test_smooth_mu.cpp Adds unit tests for anisotropic effective-μ helpers and derivatives.
tests/src/tests/friction/test_force_jacobian.cpp Adjusts force/Jacobian tests for mesh sizing and adds coverage for no-μ paths.
tests/src/tests/friction/test_anisotropic_friction.cpp Adds new anisotropic friction tests (helpers + force/Jacobian scenarios).
tests/src/tests/friction/CMakeLists.txt Registers the new anisotropic friction test file.
docs/source/tutorials/advanced_friction.rst Adds an anisotropic friction tutorial section and usage examples.
docs/source/cpp-api/friction.rst Documents anisotropic helper APIs for C++.
docs/source/python-api/friction.rst Documents anisotropic helper APIs for Python.
docs/source/references.bib Adds the matchstick model citation.
docs/source/developers/tools.rst / docs/source/developers/style_guide.rst Clarifies formatting/tooling expectations (clang-format version/style).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// NOTE: Direction-dependent anisotropic friction only makes sense in 3D
// (2D tangent space). For 2D simulations (1D tangent space), disable.
const bool is_anisotropic =
tangent_dim > 1 && collision.mu_s_aniso.squaredNorm() > 0;
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

The anisotropy enable check uses only collision.mu_s_aniso.squaredNorm() > 0, so a non-zero mu_k_aniso alone won’t activate the anisotropic path (and will also skip the dμ/dτ contribution). Consider enabling anisotropy when either mu_s_aniso or mu_k_aniso is non-zero and handling them independently if only one is provided.

Suggested change
tangent_dim > 1 && collision.mu_s_aniso.squaredNorm() > 0;
tangent_dim > 1
&& (collision.mu_s_aniso.squaredNorm() > 0
|| collision.mu_k_aniso.squaredNorm() > 0);

Copilot uses AI. Check for mistakes.
Comment on lines +334 to +337
// Build with default (isotropic) friction
tangential_collisions.build(
mesh, vertices, normal_collisions, barrier_potential, 1.0, 0.5, 0.3);

Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

This test builds TangentialCollisions from an empty NormalCollisions instance (never build()-ed), so tangential_collisions will typically be empty and all checks are skipped. To make the test meaningful, build normal_collisions for a configuration that guarantees at least one collision and REQUIRE(!tangential_collisions.empty()) before checking per-collision parameter assignment.

Copilot uses AI. Check for mistakes.
Comment on lines +368 to +372
const double dhat = 1e-2;
normal_collisions.build(mesh, vertices, dhat);

if (normal_collisions.empty()) {
return; // Skip if no collisions
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

With the current geometry the test is likely a no-op: the vertices are 0.05 apart while dhat is 1e-2, so normal_collisions.build(...) will typically produce no collisions and the test returns early. Consider reducing the separation (e.g., < dhat) and replacing the early return with REQUIRE(!normal_collisions.empty()) / REQUIRE(!tangential_collisions.empty()) so the anisotropic force path is reliably exercised.

Copilot uses AI. Check for mistakes.
Comment on lines +187 to +191
// Check if direction-dependent anisotropic friction is enabled
const bool is_anisotropic = mu_s_aniso.squaredNorm() > 0;

if (is_anisotropic) {
// Direction-dependent friction: compute effective mu based on
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

anisotropic_mu_eff_from_tau_aniso() enables anisotropy using only mu_s_aniso.squaredNorm() > 0, so setting only mu_k_aniso (with mu_s_aniso left at zero) silently falls back to isotropic and ignores kinetic anisotropy. Consider enabling anisotropy when either ellipse is non-zero and computing mu_s/mu_k independently (anisotropic when the corresponding vector is non-zero, otherwise use the scalar fallback).

Copilot uses AI. Check for mistakes.
Comment on lines 167 to +168
return collision.weight * collision.normal_force_magnitude
* mu_f0(u.norm(), collision.mu_s, collision.mu_k);
* mu_f0(u_aniso.norm(), collision.mu_s, collision.mu_k);
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Even when mu_s_aniso/mu_k_aniso are set, the potential value is still computed using only scalar collision.mu_s/collision.mu_k (effective μ is not applied here). This makes the dissipative potential (and its grad/Hessian) inconsistent with the anisotropic force path, and will break force↔potential derivative consistency for anisotropic contacts. Consider evaluating effective mu_s/mu_k from the (scaled) tangential direction here too and propagating its derivatives.

Copilot uses AI. Check for mistakes.
@ipc-sim ipc-sim deleted a comment from Copilot AI Feb 6, 2026
@ipc-sim ipc-sim deleted a comment from Copilot AI Feb 6, 2026
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants