Exemple #1
0
 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)
Exemple #2
0
def p2g(f: ti.i32):
    for p in range(0, n_particles):
        new_Jp = Jp[f, p]
        base = ti.cast(x[f, p] * inv_dx - 0.5, ti.i32)
        fx = x[f, p] * inv_dx - ti.cast(base, ti.f32)

        w = [
            0.5 * ti.sqr(1.5 - fx), 0.75 - ti.sqr(fx - 1.0),
            0.5 * ti.sqr(fx - 0.5)
        ]  # quadratic kernels
        new_F = (ti.Matrix.diag(dim=dim, val=1) +
                 dt * C[f, p]) @ F[f, p]  # deformation gradient update
        h = max(0.1, min(5, ti.exp(10 * (1.0 - new_Jp))))

        if particle_type[p] == 1:  # jelly, make it softer
            h = 0.3

        mu, la = mu_0 * h, lambda_0 * h
        if particle_type[p] == 0:  # liquid
            mu = 0.0

        U, sig, V = ti.svd(new_F)

        J = 1.0
        for d in ti.static(range(2)):
            new_sig = sig[d, d]
            if particle_type[p] == 2:  # Snow
                new_sig = min(max(sig[d, d], 1 - 2.5e-2),
                              1 + 4.5e-3)  # Plasticity
            new_Jp *= sig[d, d] / new_sig
            sig[d, d] = new_sig
            J *= new_sig
        if particle_type[
                p] == 0:  # Reset deformation gradient to avoid numerical instability
            new_F = ti.Matrix.diag(dim=dim, val=1) * ti.sqrt(J)
        elif particle_type[p] == 2:
            new_F = U @ sig @ ti.transposed(
                V)  # Reconstruct elastic deformation gradient after plasticity

        F[f + 1, p] = new_F
        Jp[f + 1, p] = new_Jp

        stress = 2 * mu * (new_F - U @ ti.transposed(V)) @ ti.transposed(
            new_F) + ti.Matrix.diag(dim=dim, val=1) * la * J * (J - 1)
        stress = (-dt * p_vol * 4 * inv_dx * inv_dx) * stress
        affine = stress + p_mass * C[f, p]

        # loop over 3x3 node neighborhood
        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]), ti.f32) - fx) * dx
                weight = w[i](0) * w[j](1)
                ti.atomic_add(grid_v_in[base + offset],
                              weight * (p_mass * v[f, p] + affine @ dpos))
                ti.atomic_add(grid_m[base + offset], weight * p_mass)
Exemple #3
0
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=dim, val=1) + dt * C[f, p]) @ F[f, p]
        J = ti.determinant(new_F)
        if particle_type[p] == 0:  # fluid
            sqrtJ = ti.sqrt(J)
            # TODO: need pow(x, 1/3)
            new_F = ti.Matrix([[sqrtJ, 0, 0], [0, sqrtJ, 0], [0, 0, 1]])

        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], [0.0, 0.0, 0.0], [0.0, 0.0, 1.0]
                       ]) * act
        cauchy = ti.Matrix(zero_matrix())
        mass = 0.0
        ident = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
        if particle_type[p] == 0:
            mass = 4
            cauchy = ti.Matrix(ident) * (J - 1) * E
        else:
            mass = 1
            cauchy = mu * (new_F @ ti.transposed(new_F)) + ti.Matrix(ident) * (
                la * ti.log(J) - mu)
        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)):
                for k in ti.static(range(3)):
                    offset = ti.Vector([i, j, k])
                    dpos = (ti.cast(ti.Vector([i, j, k]), real) - fx) * dx
                    weight = w[i](0) * w[j](1) * w[k](2)
                    grid_v_in[base + offset].atomic_add(
                        weight * (mass * v[f, p] + affine @ dpos))
                    grid_m_in[base + offset].atomic_add(weight * mass)
Exemple #4
0
def grid_op():
    for i, j in grid_m_in:
        inv_m = 1 / (grid_m_in[i, j] + 1e-10)
        v_out = inv_m * grid_v_in[i, j]
        v_out[1] -= dt * gravity
        if i < bound and v_out[0] < 0:
            v_out[0] = 0
            v_out[1] = 0
        if i > n_grid - bound and v_out[0] > 0:
            v_out[0] = 0
            v_out[1] = 0
        if j < bound and v_out[1] < 0:
            v_out[0] = 0
            v_out[1] = 0
            normal = ti.Vector([0.0, 1.0])
            lsq = ti.sqr(normal).sum()
            if lsq > 0.5:
                if ti.static(coeff < 0):
                    v_out(0).val = 0
                    v_out(1).val = 0
                else:
                    lin = (ti.transposed(v_out) @ normal)(0)
                    if lin < 0:
                        vit = v_out - lin * normal
                        lit = vit.norm() + 1e-10
                        if lit + coeff * lin <= 0:
                            v_out(0).val = 0
                            v_out(1).val = 0
                        else:
                            v_out = (1 + coeff * lin / lit) * vit
        if j > n_grid - bound and v_out[1] > 0:
            v_out[0] = 0
            v_out[1] = 0

        grid_v_out[i, j] = v_out
Exemple #5
0
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 * 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] += weight * (mass * v[f, p] + affine @ dpos)
        grid_m_in[base + offset] += weight * mass
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]
    F[f + 1, p] = new_F
    J = ti.determinant(new_F)
    r, s = ti.polar_decompose(new_F)
    cauchy = 2 * mu * (new_F - r) @ ti.transposed(new_F) + \
             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
Exemple #7
0
 def transpose():
     mat = ti.transposed(m[None])
     m[None] = mat
Exemple #8
0
 def run():
     U[None], sigma[None], V[None] = ti.svd(A[None], dt)
     UtU[None] = ti.transposed(U[None]) @ U[None]
     VtV[None] = ti.transposed(V[None]) @ V[None]
     A_reconstructed[None] = U[None] @ sigma[None] @ ti.transposed(V[None])
Exemple #9
0
def polar_decompose3d(A, dt):
    U, sig, V = ti.svd(A, dt)
    return U @ ti.transposed(V), V @ sig @ ti.transposed(V)