|
10 | 10 | import MassSpringEnergy |
11 | 11 | import GravityEnergy |
12 | 12 | import BarrierEnergy |
| 13 | +import FrictionEnergy |
13 | 14 |
|
14 | | -def step_forward(x, e, v, m, l2, k, n, o, contact_area, is_DBC, h, tol): |
| 15 | +def step_forward(x, e, v, m, l2, k, n, o, contact_area, mu, is_DBC, h, tol): |
15 | 16 | x_tilde = x + v * h # implicit Euler predictive position |
16 | 17 | x_n = copy.deepcopy(x) |
| 18 | + mu_lambda = BarrierEnergy.compute_mu_lambda(x, n, o, contact_area, mu) # compute mu * lambda for each node using x^n |
17 | 19 |
|
18 | 20 | # Newton loop |
19 | 21 | iter = 0 |
20 | | - E_last = IP_val(x, e, x_tilde, m, l2, k, n, o, contact_area, h) |
21 | | - p = search_dir(x, e, x_tilde, m, l2, k, n, o, contact_area, is_DBC, h) |
| 22 | + E_last = IP_val(x, e, x_tilde, m, l2, k, n, o, contact_area, (x - x_n) / h, mu_lambda, h) |
| 23 | + p = search_dir(x, e, x_tilde, m, l2, k, n, o, contact_area, (x - x_n) / h, mu_lambda, is_DBC, h) |
22 | 24 | while LA.norm(p, inf) / h > tol: |
23 | 25 | print('Iteration', iter, ':') |
24 | 26 | print('residual =', LA.norm(p, inf) / h) |
25 | 27 |
|
26 | 28 | # filter line search |
27 | 29 | alpha = BarrierEnergy.init_step_size(x, n, o, p) # avoid interpenetration and tunneling |
28 | | - while IP_val(x + alpha * p, e, x_tilde, m, l2, k, n, o, contact_area, h) > E_last: |
| 30 | + while IP_val(x + alpha * p, e, x_tilde, m, l2, k, n, o, contact_area, (x - x_n) / h, mu_lambda, h) > E_last: |
29 | 31 | alpha /= 2 |
30 | 32 | print('step size =', alpha) |
31 | 33 |
|
32 | 34 | x += alpha * p |
33 | | - E_last = IP_val(x, e, x_tilde, m, l2, k, n, o, contact_area, h) |
34 | | - p = search_dir(x, e, x_tilde, m, l2, k, n, o, contact_area, is_DBC, h) |
| 35 | + E_last = IP_val(x, e, x_tilde, m, l2, k, n, o, contact_area, (x - x_n) / h, mu_lambda, h) |
| 36 | + p = search_dir(x, e, x_tilde, m, l2, k, n, o, contact_area, (x - x_n) / h, mu_lambda, is_DBC, h) |
35 | 37 | iter += 1 |
36 | 38 |
|
37 | 39 | v = (x - x_n) / h # implicit Euler velocity update |
38 | 40 | return [x, v] |
39 | 41 |
|
40 | | -def IP_val(x, e, x_tilde, m, l2, k, n, o, contact_area, h): |
41 | | - return InertiaEnergy.val(x, x_tilde, m) + h * h * (MassSpringEnergy.val(x, e, l2, k) + GravityEnergy.val(x, m) + BarrierEnergy.val(x, n, o, contact_area)) # implicit Euler |
| 42 | +def IP_val(x, e, x_tilde, m, l2, k, n, o, contact_area, v, mu_lambda, h): |
| 43 | + return InertiaEnergy.val(x, x_tilde, m) + h * h * (MassSpringEnergy.val(x, e, l2, k) + GravityEnergy.val(x, m) + BarrierEnergy.val(x, n, o, contact_area) + FrictionEnergy.val(v, mu_lambda, h, n)) # implicit Euler |
42 | 44 |
|
43 | | -def IP_grad(x, e, x_tilde, m, l2, k, n, o, contact_area, h): |
44 | | - return InertiaEnergy.grad(x, x_tilde, m) + h * h * (MassSpringEnergy.grad(x, e, l2, k) + GravityEnergy.grad(x, m) + BarrierEnergy.grad(x, n, o, contact_area)) # implicit Euler |
| 45 | +def IP_grad(x, e, x_tilde, m, l2, k, n, o, contact_area, v, mu_lambda, h): |
| 46 | + return InertiaEnergy.grad(x, x_tilde, m) + h * h * (MassSpringEnergy.grad(x, e, l2, k) + GravityEnergy.grad(x, m) + BarrierEnergy.grad(x, n, o, contact_area) + FrictionEnergy.grad(v, mu_lambda, h, n)) # implicit Euler |
45 | 47 |
|
46 | | -def IP_hess(x, e, x_tilde, m, l2, k, n, o, contact_area, h): |
| 48 | +def IP_hess(x, e, x_tilde, m, l2, k, n, o, contact_area, v, mu_lambda, h): |
47 | 49 | IJV_In = InertiaEnergy.hess(x, x_tilde, m) |
48 | 50 | IJV_MS = MassSpringEnergy.hess(x, e, l2, k) |
49 | 51 | IJV_B = BarrierEnergy.hess(x, n, o, contact_area) |
| 52 | + IJV_F = FrictionEnergy.hess(v, mu_lambda, h, n) |
50 | 53 | IJV_MS[2] *= h * h # implicit Euler |
51 | 54 | IJV_B[2] *= h * h # implicit Euler |
| 55 | + IJV_F[2] *= h * h # implicit Euler |
52 | 56 | IJV_In_MS = np.append(IJV_In, IJV_MS, axis=1) |
53 | | - IJV = np.append(IJV_In_MS, IJV_B, axis=1) |
| 57 | + IJV_In_MS_B = np.append(IJV_In_MS, IJV_B, axis=1) |
| 58 | + IJV = np.append(IJV_In_MS_B, IJV_F, axis=1) |
54 | 59 | H = sparse.coo_matrix((IJV[2], (IJV[0], IJV[1])), shape=(len(x) * 2, len(x) * 2)).tocsr() |
55 | 60 | return H |
56 | 61 |
|
57 | | -def search_dir(x, e, x_tilde, m, l2, k, n, o, contact_area, is_DBC, h): |
58 | | - projected_hess = IP_hess(x, e, x_tilde, m, l2, k, n, o, contact_area, h) |
59 | | - reshaped_grad = IP_grad(x, e, x_tilde, m, l2, k, n, o, contact_area, h).reshape(len(x) * 2, 1) |
| 62 | +def search_dir(x, e, x_tilde, m, l2, k, n, o, contact_area, v, mu_lambda, is_DBC, h): |
| 63 | + projected_hess = IP_hess(x, e, x_tilde, m, l2, k, n, o, contact_area, v, mu_lambda, h) |
| 64 | + reshaped_grad = IP_grad(x, e, x_tilde, m, l2, k, n, o, contact_area, v, mu_lambda, h).reshape(len(x) * 2, 1) |
60 | 65 | # eliminate DOF by modifying gradient and Hessian for DBC: |
61 | 66 | for i, j in zip(*projected_hess.nonzero()): |
62 | 67 | if is_DBC[int(i / 2)] | is_DBC[int(j / 2)]: |
|
0 commit comments