def polar(): R, S = ti.polar_decompose(m[None], dt) r[None] = R s[None] = S m[None] = R @ S I[None] = R @ R.transpose() D[None] = S - S.transpose()
def polar(): R, S = ti.polar_decompose(m[None], dt) r[None] = R s[None] = S m[None] = R @ S I[None] = R @ ti.transposed(R) D[None] = S - ti.transposed(S)
def p2g(f: ti.i32): for p in range(0, n_particles): base = ti.cast(x[f, p] * inv_dx - 0.5, ti.i32) fx = x[f, p] * inv_dx - ti.cast(base, ti.i32) w = [ 0.5 * ti.sqr(1.5 - fx), 0.75 - ti.sqr(fx - 1), 0.5 * ti.sqr(fx - 0.5) ] new_F = (ti.Matrix.diag(dim=2, val=1) + dt * C[f, p]) @ F[f, p] J = ti.determinant(new_F) if particle_type[p] == 0: # fluid sqrtJ = ti.sqrt(J) new_F = ti.Matrix([[sqrtJ, 0], [0, sqrtJ]]) F[f + 1, p] = new_F r, s = ti.polar_decompose(new_F) act_id = actuator_id[p] act = actuation[f, ti.max(0, act_id)] * act_strength if act_id == -1: act = 0.0 # ti.print(act) A = ti.Matrix([[0.0, 0.0], [0.0, 1.0]]) * act cauchy = ti.Matrix([[0.0, 0.0], [0.0, 0.0]]) mass = 0.0 if particle_type[p] == 0: mass = 4 cauchy = ti.Matrix([[1.0, 0.0], [0.0, 0.1]]) * (J - 1) * E else: mass = 1 cauchy = 2 * mu * (new_F - r) @ ti.transposed(new_F) + \ ti.Matrix.diag(2, la * (J - 1) * J) cauchy += new_F @ A @ ti.transposed(new_F) stress = -(dt * p_vol * 4 * inv_dx * inv_dx) * cauchy affine = stress + mass * C[f, p] for i in ti.static(range(3)): for j in ti.static(range(3)): offset = ti.Vector([i, j]) dpos = (ti.cast(ti.Vector([i, j]), real) - fx) * dx weight = w[i](0) * w[j](1) grid_v_in[base + offset].atomic_add( weight * (mass * v[f, p] + affine @ dpos)) grid_m_in[base + offset].atomic_add(weight * mass)
def p2g(f: ti.i32): for p in range(n_particles): base = ti.cast(x[f, p] * inv_dx - 0.5, ti.i32) fx = x[f, p] * inv_dx - ti.cast(base, ti.i32) w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2] new_F = (ti.Matrix.diag(dim=2, val=1) + dt * C[f, p]) @ F[f, p] F[f + 1, p] = new_F J = (new_F).determinant() r, s = ti.polar_decompose(new_F) cauchy = 2 * mu * (new_F - r) @ new_F.transpose() + \ ti.Matrix.diag(2, la * (J - 1) * J) stress = -(dt * p_vol * 4 * inv_dx * inv_dx) * cauchy affine = stress + p_mass * C[f, p] for i in ti.static(range(3)): for j in ti.static(range(3)): offset = ti.Vector([i, j]) dpos = (ti.cast(ti.Vector([i, j]), real) - fx) * dx weight = w[i](0) * w[j](1) grid_v_in[f, base + offset] += weight * (p_mass * v[f, p] + affine @ dpos) grid_m_in[f, base + offset] += weight * p_mass
def foo(): ti.polar_decompose(m, ti.f32)
def step(): for i, j in grid_v: grid_v[i, j] = [0, 0] grid_m[i, j] = 0 # 1. p2g for p in x: base = (x[p] * inv_dx - 0.5).cast(int) fx = x[p] * inv_dx - base.cast(float) # Quadratic kernels [http://mpm.graphics Eqn. 123, with x=fx, fx-1,fx-2] w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2] # 1.1 F update F[p] = (ti.Matrix.identity(dt=ti.f32, n=2) + dt * C[p]) @ F[p] r, _ = ti.polar_decompose(F[p]) U, sig, V = ti.svd(F[p]) J[p] = F[p].determinant() # 1.2 Cauchy Stress mu = 0 PF = 2 * mu * (F[p] - U @ V.T()) @ F[p].T() + lambda_0 * ( J[p] - 1) * J[p] * ti.Matrix.identity(dt=ti.f32, n=2) Dinv = 4 * inv_dx * inv_dx stress = -dt * p_vol * Dinv * PF # 1.3 affine affine = stress + p_mass * C[p] for i, j in ti.static(ti.ndrange(3, 3)): offset = ti.Vector([i, j]) dpos = (offset.cast(float) - fx) * dx weight = w[i][0] * w[j][1] grid_v[base + offset] += weight * (p_mass * v[p] + affine @ dpos) grid_m[base + offset] += weight * p_mass # 2. update grad momentum for i, j in grid_m: if grid_m[i, j] > 0: grid_v[i, j] = (1 / grid_m[i, j]) * grid_v[i, j] # Momentum to velocity grid_v[i, j][1] -= dt * 200 # gravity if i < 3 and grid_v[i, j][0] < 0: grid_v[i, j][0] = 0 # Boundary conditions if i > n_grid - 3 and grid_v[i, j][0] > 0: grid_v[i, j][0] = 0 if j < 3 and grid_v[i, j][1] < 0: grid_v[i, j][1] = 0 if j > n_grid - 3 and grid_v[i, j][1] > 0: grid_v[i, j][1] = 0 # 3. g2p for p in x: # grid to particle (G2P) base = (x[p] * inv_dx - 0.5).cast(int) fx = x[p] * inv_dx - base.cast(float) w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1.0)**2, 0.5 * (fx - 0.5)**2] new_v = ti.Vector.zero(ti.f32, 2) new_C = ti.Matrix.zero(ti.f32, 2, 2) for i, j in ti.static(ti.ndrange( 3, 3)): # loop over 3x3 grid node neighborhood dpos = ti.Vector([i, j]).cast(float) - fx g_v = grid_v[base + ti.Vector([i, j])] weight = w[i][0] * w[j][1] new_v += weight * g_v new_C += 4 * inv_dx * weight * g_v.outer_product(dpos) v[p], C[p] = new_v, new_C x[p] += dt * v[p]