def inverse(self): assert self.n == self.m, 'Only square matrices are invertible' if self.n == 1: return Matrix([1 / self(0, 0)]) elif self.n == 2: inv_det = impl.expr_init(1.0 / self.determinant(self)) # Discussion: https://github.com/taichi-dev/taichi/pull/943#issuecomment-626344323 return inv_det * Matrix([[self(1, 1), -self(0, 1)], [-self(1, 0), self(0, 0)]]).variable() elif self.n == 3: n = 3 import taichi as ti inv_determinant = ti.expr_init(1.0 / ti.determinant(self)) entries = [[0] * n for _ in range(n)] def E(x, y): return self(x % n, y % n) for i in range(n): for j in range(n): entries[j][i] = ti.expr_init( inv_determinant * (E(i + 1, j + 1) * E(i + 2, j + 2) - E(i + 2, j + 1) * E(i + 1, j + 2))) return Matrix(entries) elif self.n == 4: n = 4 import taichi as ti inv_determinant = ti.expr_init(1.0 / ti.determinant(self)) entries = [[0] * n for _ in range(n)] def E(x, y): return self(x % n, y % n) for i in range(n): for j in range(n): entries[j][i] = ti.expr_init( inv_determinant * (-1)**(i + j) * ((E(i + 1, j + 1) * (E(i + 2, j + 2) * E(i + 3, j + 3) - E(i + 3, j + 2) * E(i + 2, j + 3)) - E(i + 2, j + 1) * (E(i + 1, j + 2) * E(i + 3, j + 3) - E(i + 3, j + 2) * E(i + 1, j + 3)) + E(i + 3, j + 1) * (E(i + 1, j + 2) * E(i + 2, j + 3) - E(i + 2, j + 2) * E(i + 1, j + 3))))) return Matrix(entries) else: raise Exception( "Inversions of matrices with sizes >= 5 are not supported")
def inverse(self): assert self.n == self.m, 'Only square matrices are invertible' if self.n == 1: return Matrix([1 / self(0, 0)]) elif self.n == 2: inv_det = impl.expr_init(1.0 / self.determinant(self)) return inv_det * Matrix([[self(1, 1), -self(0, 1)], [-self(1, 0), self(0, 0)]]) elif self.n == 3: n = 3 import taichi as ti inv_determinant = ti.expr_init(1.0 / ti.determinant(self)) entries = [[0] * n for _ in range(n)] def E(x, y): return self(x % n, y % n) for i in range(n): for j in range(n): entries[j][i] = ti.expr_init( inv_determinant * (E(i + 1, j + 1) * E(i + 2, j + 2) - E(i + 2, j + 1) * E(i + 1, j + 2))) return Matrix(entries) else: raise Exception( "Inversions of matrices with sizes >= 4 are not supported")
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)
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