Skip to content

Commit 801f82c

Browse files
authored
Replace smooth mu with a piecewise quadratic function (#179)
1 parent f6ae3b7 commit 801f82c

File tree

10 files changed

+1314
-359
lines changed

10 files changed

+1314
-359
lines changed
-435 Bytes
Loading
-281 Bytes
Loading

docs/source/_static/img/mu.png

131 Bytes
Loading

docs/source/_static/img/mu_f1.png

62 Bytes
Loading

docs/source/_static/img/mu_f1a.png

20 Bytes
Loading

docs/source/tutorials/adhesion.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,4 @@ We integrate their product to obtain a smooth tangential adhesion mollifier:
201201
.. figure:: /_static/img/int_mu_f1a_dx.png
202202
:align: center
203203

204-
Integrated mollifier :math:`\int \mu(y) f_1^a(y) \mathrm{d} y` where :math:`\mu_s = 1`, :math:`\mu_k = 0.1`, and :math:`\epsilon_v = 0.001`.
204+
Integrated mollifier :math:`\int \mu(y) f_1^a(y) \mathrm{d} y` where :math:`y=\|\mathbf{u}\|`, :math:`\mu_s = 1`, :math:`\mu_k = 0.1`, and :math:`\epsilon_v = 0.001`.

docs/source/tutorials/advanced_friction.rst

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,10 @@ Smooth :math:`\mu`
108108
When adding separate coefficients for static and kinetic friction, we need to maintain the :math:`C^1` continuity of the friction force. This lead us to define a smooth coefficient of friction :math:`\mu(y)` that transitions between the static and kinetic coefficients based on the magnitude of the relative velocity :math:`y = \|\mathbf{u}\|`. The smooth coefficient of friction is defined as
109109

110110
.. math::
111-
\mu(y) = \begin{cases} \mu_{s} + \left(\mu_{k} - \mu_{s}\right) \left(\frac{3 y^{2}}{\epsilon_{v}^{2}} - \frac{2 y^{3}}{\epsilon_{v}^{3}}\right) & \text{for}\: 0 \leq y \leq \epsilon_{v}\\
112-
\mu_{k} & \text{otherwise}.
111+
\mu(y) = \begin{cases}
112+
2(\mu_{k} - \mu_{s})\frac{y^{2}}{\epsilon_{v}^{2}} + \mu_{s} & \text{for}\: y \leq \frac{\epsilon_{v}}{2} \\
113+
-2(\mu_{k} - \mu_{s})\frac{\left(\epsilon_{v} - y\right)^{2}}{\epsilon_{v}^{2}} + \mu_k & \text{for}\: y \leq \epsilon_{v} \\
114+
\mu_{k} & \text{for}\: y > \epsilon_{v}
113115
\end{cases}
114116
115117
We plot the smooth coefficient of friction :math:`\mu(y)` below:
@@ -132,13 +134,9 @@ Replacing the constant coefficient of friction :math:`\mu` with a smooth functio
132134
However, :math:`\frac{\mathrm{d}}{\mathrm{d}y} \mu(y) f_0(y) \neq \mu(y) f_1(y)`, so we need to adjust the integrated mollifier by integrating the product of the smooth coefficient of friction and the mollifier:
133135

134136
.. math::
135-
\int \mu(y) f_1(y) \mathrm{d} y = \begin{cases}
136-
\frac{\epsilon_{v}^{6} \left(17 \mu_{k} - 7 \mu_{s}\right) + 30 \epsilon_{v}^{4} \mu_{s} y^{2} - 10 \epsilon_{v}^{3} \mu_{s} y^{3} + 45 \epsilon_{v}^{2} \left(\mu_{k} - \mu_{s}\right) y^{4} + 42 \epsilon_{v} \left(- \mu_{k} + \mu_{s}\right) y^{5} + 10 \left(\mu_{k} - \mu_{s}\right) y^{6}}{30 \epsilon_{v}^{5}} & \text{for}\: \epsilon_{v} > y \\
137-
\mu_{k} y & \text{otherwise}
138-
\end{cases}.
139-
140-
141-
137+
\int \mu(y) f_1(y) \mathrm{d} y = \begin{cases} \frac{\frac{\epsilon_{v}^{5} \left(27 \mu_{k} - 11 \mu_{s}\right)}{48} + \epsilon_{v}^{3} \mu_{s} y^{2} - \frac{\epsilon_{v}^{2} \mu_{s} y^{3}}{3} + \epsilon_{v} y^{4} \left(\mu_{k} - \mu_{s}\right) + \frac{2 y^{5} \left(- \mu_{k} + \mu_{s}\right)}{5}}{\epsilon_{v}^{4}} & \text{for}\: y \leq \frac{\epsilon_{v}}{2} \\
138+
\frac{\epsilon_{v}^{5} \left(9 \mu_{k} - 4 \mu_{s}\right) + 15 \epsilon_{v}^{3} y^{2} \left(- \mu_{k} + 2 \mu_{s}\right) + 5 \epsilon_{v}^{2} y^{3} \left(9 \mu_{k} - 10 \mu_{s}\right) - 30 \epsilon_{v} y^{4} \left(\mu_{k} - \mu_{s}\right) + 6 y^{5} \left(\mu_{k} - \mu_{s}\right)}{15 \epsilon_{v}^{4}} & \text{for}\: y \leq \epsilon_{v} \\
139+
\mu_{k} y & \text{for}\: y > \epsilon_v \end{cases}
142140
143141
The following plot shows the behavior of the integrated mollifier multiplied by the smooth coefficient of friction:
144142

@@ -155,11 +153,10 @@ While this approach provides a smooth transition between static and kinetic fric
155153
1. The product :math:`\mu(y) f_1(y)` underestimates the friction force in the static regime, which may lead to less accurate simulations of static friction.
156154
- This is, when :math:`\mu_k < \mu_s` and :math:`|y| \leq \epsilon_v`, :math:`\max(\mu(y) f_1(y)) < \mu_s`.
157155
- We could address this by scaling by :math:`\frac{\max(\mu(y) f_1(y))}{\mu_s}`, but computing the maximum is non-trivial.
158-
2. The combined function :math:`\mu(y) f_1(y)` is a degree 5 polynomial, which is more complex than the original mollifier :math:`f_1(y)` (degree 2). This may lead to more difficult to optimize problems. There are two options to address this:
159-
a. Replacing :math:`\mu(y)` with a piecewise quadratic function would reduce the degree to 4, but it would still be more complex than the original mollifier.
160-
b. Replacing :math:`\mu(y) f_1(y)` with a piecewise quadratic function that has the desired behavior. This help with 1. as well. However making it backwards compatible with the original mollifier is challenging.
156+
2. The combined function :math:`\mu(y) f_1(y)` is a degree 4 polynomial, which is more complex than the original mollifier :math:`f_1(y)` (degree 2). This may lead to more difficult to optimize problems.
157+
- We could replace :math:`\mu(y) f_1(y)` with a piecewise quadratic function that has the desired behavior. This help with (1) as well. However making it backwards compatible with the original mollifier is challenging.
161158

162-
If you have suggestions for improving this approach or alternative methods, please reach out on our `GitHub Discussions <https://github.com/ipc-sim/ipc-toolkit/discussions>`.
159+
If you have suggestions for improving this approach or alternative methods, please reach out on our `GitHub Discussions <https://github.com/ipc-sim/ipc-toolkit/discussions>`_.
163160

164161
Future Directions
165162
-----------------

notebooks/separate_mu.ipynb

Lines changed: 1246 additions & 324 deletions
Large diffs are not rendered by default.

src/ipc/adhesion/adhesion.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,25 @@ double smooth_mu_a0(
135135
{
136136
assert(eps_a > 0);
137137
const double delta_mu = mu_k - mu_s;
138-
if (mu_s == mu_k || y <= 0 || y >= eps_a) {
138+
if (y <= 0) {
139+
return 0;
140+
} else if (mu_s == mu_k || y >= eps_a) {
139141
// If the static and kinetic friction coefficients are equal, simplify.
140-
const double c = (7 / 30.) * eps_a * delta_mu;
142+
const double c = (11 / 48.) * eps_a * delta_mu;
141143
return mu_k * tangential_adhesion_f0(y, eps_a) - c;
142144
} else {
143145
const double z = y / eps_a;
144-
return y * z
145-
* (z * (z * (z * (z / 3 - 1.4) + 1.5) * delta_mu - mu_s / 3)
146-
+ mu_s);
146+
if (y < 0.5 * eps_a) {
147+
return y * z
148+
* (z * (z * (1 - 0.4 * z) * delta_mu - mu_s / 3.0) + mu_s);
149+
} else {
150+
return y * z
151+
* (z
152+
* (z * (0.4 * z - 2) * delta_mu + 3 * mu_k
153+
- (10.0 / 3.0) * mu_s)
154+
- mu_k + 2 * mu_s)
155+
+ (3.0 / 80.0) * eps_a * delta_mu;
156+
}
147157
}
148158
}
149159

@@ -174,14 +184,20 @@ double smooth_mu_a2_x_minus_mu_a1_over_x3(
174184
const double y, const double mu_s, const double mu_k, const double eps_a)
175185
{
176186
assert(eps_a > 0);
177-
if (mu_s == mu_k || y <= 0 || y >= eps_a) {
187+
assert(y >= 0);
188+
if (mu_s == mu_k || y >= eps_a) {
178189
// If the static and kinetic friction coefficients are equal, simplify.
179190
return mu_k * tangential_adhesion_f2_x_minus_f1_over_x3(y, eps_a);
180191
} else {
181192
const double delta_mu = mu_k - mu_s;
182193
const double z = 1 / eps_a;
183-
return z * z
184-
* (z * (z * y * (z * y * 8 - 21) + 12) * delta_mu - mu_s / y);
194+
if (y < 0.5 * eps_a) {
195+
return z * z * (z * (8 - 6 * z * y) * delta_mu - mu_s / y);
196+
} else {
197+
return z * z
198+
* (z * (6 * z * y - 16) * delta_mu
199+
+ (9 * mu_k - 10 * mu_s) / y);
200+
}
185201
}
186202
}
187203

src/ipc/friction/smooth_mu.cpp

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ double smooth_mu(
1515
// If the static and kinetic friction coefficients are equal, simplify.
1616
return mu_k;
1717
} else {
18-
const double y_over_eps_v = std::abs(y) / eps_v;
19-
return (mu_k - mu_s) * (3 - 2 * y_over_eps_v) * y_over_eps_v
20-
* y_over_eps_v
21-
+ mu_s;
18+
const double z = std::abs(y) / eps_v;
19+
if (std::abs(y) < 0.5 * eps_v) {
20+
return 2 * (mu_k - mu_s) * z * z + mu_s;
21+
} else {
22+
return -2 * (mu_k - mu_s) * (z * (z - 2) + 1) + mu_k;
23+
}
2224
}
2325
}
2426

@@ -30,8 +32,12 @@ double smooth_mu_derivative(
3032
// If the static and kinetic friction coefficients are equal, simplify.
3133
return 0;
3234
} else {
33-
const double y_over_eps_v = std::abs(y) / eps_v;
34-
return (mu_k - mu_s) * (6 - 6 * y_over_eps_v) * y_over_eps_v / eps_v;
35+
const double z = std::abs(y) / eps_v;
36+
if (std::abs(y) < 0.5 * eps_v) {
37+
return 4 * (mu_k - mu_s) * z / eps_v;
38+
} else {
39+
return -4 * (mu_k - mu_s) * (z - 1) / eps_v;
40+
}
3541
}
3642
}
3743

@@ -44,11 +50,19 @@ double smooth_mu_f0(
4450
return mu_k * smooth_friction_f0(y, eps_v);
4551
} else {
4652
const double delta_mu = mu_k - mu_s;
47-
const double c = eps_v * (17 * mu_k - 7 * mu_s) / 30;
4853
const double z = std::abs(y) / eps_v;
49-
return y * z
50-
* (z * (z * (z * (z / 3 - 1.4) + 1.5) * delta_mu - mu_s / 3) + mu_s)
51-
+ c;
54+
if (std::abs(y) < 0.5 * eps_v) {
55+
return y * z
56+
* (z * (z * (1 - 0.4 * z) * delta_mu - mu_s / 3.0) + mu_s)
57+
+ (9.0 / 16.0) * eps_v * mu_k - (11.0 / 48.0) * eps_v * mu_s;
58+
} else {
59+
return y * z
60+
* (z
61+
* (z * (0.4 * z - 2) * delta_mu
62+
+ (3 * mu_k - (10.0 / 3.0) * mu_s))
63+
+ (2 * mu_s - mu_k))
64+
+ 0.6 * eps_v * mu_k - (4.0 / 15.0) * eps_v * mu_s;
65+
}
5266
}
5367
}
5468

@@ -82,13 +96,19 @@ double smooth_mu_f2_x_minus_mu_f1_over_x3(
8296
{
8397
assert(eps_v > 0);
8498
if (mu_s == mu_k || std::abs(y) >= eps_v) {
85-
// If the static and kinetic friction coefficients are equal, simplify.
99+
// If the static and kinetic friction coefficients are equal,
100+
// simplify.
86101
return mu_k * smooth_friction_f2_x_minus_f1_over_x3(y, eps_v);
87102
} else {
88103
const double delta_mu = mu_k - mu_s;
89104
const double z = 1 / eps_v;
90-
return z * z
91-
* (z * (z * y * (z * y * 8 - 21) + 12) * delta_mu - mu_s / y);
105+
if (std::abs(y) < 0.5 * eps_v) {
106+
return z * z * (z * (8 - 6 * y * z) * delta_mu - mu_s / y);
107+
} else {
108+
return z * z
109+
* (z * (6 * y * z - 16) * delta_mu
110+
+ (9 * mu_k - 10 * mu_s) / y);
111+
}
92112
}
93113
}
94114

0 commit comments

Comments
 (0)