import taichi as ti ti.init(arch=ti.cpu) dim = 2 n_particles = 8192 n_grid = 32 dx = 1 / n_grid inv_dx = 1 / dx dt = 2.0e-3 use_apic = False x = ti.Vector(dim, dt=ti.f32, shape=n_particles) # 粒子的位置 v = ti.Vector(dim, dt=ti.f32, shape=n_particles) # 粒子的速度 C = ti.Matrix(dim, dim, dt=ti.f32, shape=n_particles) # 粒子的 C 矩阵(APIC 计算) grid_v = ti.Vector(dim, dt=ti.f32, shape=(n_grid, n_grid)) # 速度场 grid_m = ti.var(dt=ti.f32, shape=(n_grid, n_grid)) # 质量场 @ti.func def clamp_pos(pos): return ti.Vector( [max(min(0.95, pos[0]), 0.05), max(min(0.95, pos[1]), 0.05)]) @ti.kernel def substep_PIC(): # TODO step1. p2g for p in x: # random x: [0.2,0.8] # TODO step1.1. 确定所在的左下角 grid
def substep(): # set zero initial state for both water/sand grid for i, j in grid_sm: grid_sv[i, j], grid_wv[i, j] = [0, 0], [0, 0] grid_sm[i, j], grid_wm[i, j] = 0, 0 grid_sf[i, j], grid_wf[i, j] = [0, 0], [0, 0] # P2G (sand's part) for p in range(n_s_particles): base = (x_s[p] * inv_dx - 0.5).cast(int) if base[0] < 0 or base[1] < 0 or base[0] >= n_grid - 2 or base[ 1] >= n_grid - 2: continue fx = x_s[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] U, sig, V = ti.svd(F_s[p]) inv_sig = sig.inverse() e = ti.Matrix([[ti.log(sig[0, 0]), 0], [0, ti.log(sig[1, 1])]]) stress = U @ (2 * mu_s * inv_sig @ e + lambda_s * e.trace() * inv_sig) @ V.transpose() # formula (25) stress = (-p_vol * 4 * inv_dx * inv_dx) * stress @ F_s[p].transpose() # stress *= h(e) # print(h(e)) affine = s_mass * C_s[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_sv[base + offset] += weight * (s_mass * v_s[p] + affine @ dpos) grid_sm[base + offset] += weight * s_mass grid_sf[base + offset] += weight * stress @ dpos # P2G (water's part): for p in range(n_w_particles): base = (x_w[p] * inv_dx - 0.5).cast(int) fx = x_w[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] stress = w_k * (1 - 1 / (J_w[p]**w_gamma)) stress = (-p_vol * 4 * inv_dx * inv_dx) * stress * J_w[p] # stress = -4 * 400 * p_vol * (J_w[p] - 1) / dx ** 2 (special case when gamma equals to 1) affine = w_mass * C_w[p] # affine = ti.Matrix([[stress, 0], [0, stress]]) + w_mass * C_w[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_wv[base + offset] += weight * (w_mass * v_w[p] + affine @ dpos) grid_wm[base + offset] += weight * w_mass grid_wf[base + offset] += weight * stress * dpos # Update Grids Momentum for i, j in grid_sm: if grid_sm[i, j] > 0: grid_sv[i, j] = ( 1 / grid_sm[i, j]) * grid_sv[i, j] # Momentum to velocity if grid_wm[i, j] > 0: grid_wv[i, j] = (1 / grid_wm[i, j]) * grid_wv[i, j] # Momentum exchange cE = (n * n * w_rho * gravity[1]) / k_hat # drag coefficient if grid_sm[i, j] > 0 and grid_wm[i, j] > 0: sm, wm = grid_sm[i, j], grid_wm[i, j] sv, wv = grid_sv[i, j], grid_wv[i, j] d = cE * sm * wm M = ti.Matrix([[sm, 0], [0, wm]]) D = ti.Matrix([[-d, d], [d, -d]]) V = ti.Matrix.rows([grid_sv[i, j], grid_wv[i, j]]) G = ti.Matrix.rows([gravity, gravity]) F = ti.Matrix.rows([grid_sf[i, j], grid_wf[i, j]]) A = M + dt * D B = M @ V + dt * (M @ G + F) X = A.inverse() @ B grid_sv[i, j], grid_wv[i, j] = ti.Vector( [X[0, 0], X[0, 1]]), ti.Vector([X[1, 0], X[1, 1]]) elif grid_sm[i, j] > 0: grid_sv[i, j] += dt * (gravity + grid_sf[i, j] / grid_sm[i, j] ) # Update explicit force elif grid_wm[i, j] > 0: grid_wv[i, j] += dt * (gravity + grid_wf[i, j] / grid_wm[i, j]) normal = ti.Vector.zero(float, 2) if grid_sm[i, j] > 0: if i < 3 and grid_sv[i, j][0] < 0: normal = ti.Vector([1, 0]) if i > n_grid - 3 and grid_sv[i, j][0] > 0: normal = ti.Vector([-1, 0]) if j < 3 and grid_sv[i, j][1] < 0: normal = ti.Vector([0, 1]) if j > n_grid - 3 and grid_sv[i, j][1] > 0: normal = ti.Vector([0, -1]) if not (normal[0] == 0 and normal[1] == 0): # Apply friction s = grid_sv[i, j].dot(normal) if s <= 0: v_normal = s * normal v_tangent = grid_sv[ i, j] - v_normal # divide velocity into normal and tangential parts vt = v_tangent.norm() if vt > 1e-12: grid_sv[i, j] = v_tangent - ( vt if vt < -mu_b * s else -mu_b * s) * ( v_tangent / vt) # The Coulomb friction law if grid_wm[i, j] > 0: if i < 3 and grid_wv[i, j][0] < 0: grid_wv[i, j][0] = 0 # Boundary conditions if i > n_grid - 3 and grid_wv[i, j][0] > 0: grid_wv[i, j][0] = 0 if j < 3 and grid_wv[i, j][1] < 0: grid_wv[i, j][1] = 0 if j > n_grid - 3 and grid_wv[i, j][1] > 0: grid_wv[i, j][1] = 0 # G2P (water's part) for p in range(n_w_particles): base = (x_w[p] * inv_dx - 0.5).cast(int) fx = x_w[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(float, 2) new_C = ti.Matrix.zero(float, 2, 2) for i, j in ti.static(ti.ndrange(3, 3)): dpos = ti.Vector([i, j]).cast(float) - fx g_v = grid_wv[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) J_w[p] = (1 + dt * new_C.trace()) * J_w[p] v_w[p], C_w[p] = new_v, new_C x_w[p] += dt * v_w[p] # G2P (sand's part) for p in range(n_s_particles): base = (x_s[p] * inv_dx - 0.5).cast(int) if base[0] < 0 or base[1] < 0 or base[0] >= n_grid - 2 or base[ 1] >= n_grid - 2: continue fx = x_s[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(float, 2) new_C = ti.Matrix.zero(float, 2, 2) phi_s[p] = 0.0 # Saturation 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_sv[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) if grid_sm[base + ti.Vector([i, j])] > 0 and grid_wm[ base + ti.Vector([i, j])] > 0: phi_s[p] += weight # formula (24) F_s[p] = (ti.Matrix.identity(float, 2) + dt * new_C) @ F_s[p] v_s[p], C_s[p] = new_v, new_C x_s[p] += dt * v_s[p] U, sig, V = ti.svd(F_s[p]) e = ti.Matrix([[ti.log(sig[0, 0]), 0], [0, ti.log(sig[1, 1])]]) new_e, dq = project(e, p) hardening(dq, p) new_F = U @ ti.Matrix([[ti.exp(new_e[0, 0]), 0], [0, ti.exp(new_e[1, 1])]]) @ V.transpose() vc_s[p] += -ti.log(new_F.determinant()) + ti.log( F_s[p].determinant()) # formula (26) F_s[p] = new_F
import taichi as ti import numpy as np ti.init() N = 320 img = ti.Vector(3, dt=ti.f32, shape=(N, N)) # 画布 canvas = ti.Vector(3, dt=ti.f32, shape=(N * 2, N)) F = ti.Matrix(2, 2, dt=ti.f32, shape=()) cursor_rest = ti.Vector(2, dt=ti.f32, shape=()) cursor_deformed = ti.Vector(2, dt=ti.f32, shape=()) img.from_numpy(ti.imread('bob.png')[:, :, :3].astype(np.float32) / 255) @ti.kernel def paint(): for i, j in canvas: if i < N: canvas[i, j] = img[i, j] pass else: x_deformed = ti.Vector([(i - N) / N - 0.5, j / N - 0.5]) Finv = F[None].inverse() x_rest = Finv @ x_deformed p = min(N - 1, max(0, int((x_rest[0] + 0.5) * N))) q = min(N - 1, max(0, int((x_rest[1] + 0.5) * N))) canvas[i, j] = img[p, q]
def _var(cls, shape=None): return ti.Matrix(3, 3, ti.f32, shape), ti.Vector.var(3, ti.f32, shape)
def inc(): for i in x(0, 0): delta = ti.Matrix([[3, 0], [0, 0]]) x[i][1, 1] = x[i][0, 0] + 1 x[i] = x[i] + delta x[i] += delta
def one(dt, n): import taichi as ti return ti.Matrix([[ti.cast(1, dt) for _ in range(n)] for _ in range(n)])
def identity(dt, n): import taichi as ti return ti.Matrix([[ti.cast(int(i == j), dt) for j in range(n)] for i in range(n)])
def rotateZ(p: ti.Vector, ang: ti.f32) -> ti.Vector: rmat: ti.Matrix = ti.Matrix([[ti.cos(ang), -ti.sin(ang), 0.0], [ti.sin(ang), ti.cos(ang), 0.0], [0.0, 0.0, 1.0]]) return rmat @ p
imgSize = 720 screenRes = ti.Vector([imgSize, imgSize]) img = ti.Vector(3, dt=ti.f32, shape=[imgSize, imgSize]) depth = ti.var(dt=ti.f32, shape=[imgSize, imgSize]) gui = ti.GUI('Cloth down simulation', res=(imgSize, imgSize)) clothWid = 4.0 clothHgt = 4.0 clothResX = 31 clothResY = 31 pos_pre = ti.Vector(3, dt=ti.f32, shape=(clothResX + 1, clothResY + 1)) pos = ti.Vector(3, dt=ti.f32, shape=(clothResX + 1, clothResY + 1)) vel = ti.Vector(3, dt=ti.f32, shape=(clothResX + 1, clothResY + 1)) F = ti.Vector(3, dt=ti.f32, shape=(clothResX + 1, clothResY + 1)) J = ti.Matrix(3, 3, dt=ti.f32, shape=(clothResX + 1, clothResY + 1)) eye = ti.Vector(3, dt=ti.f32, shape=()) target = ti.Vector(3, dt=ti.f32, shape=()) up = ti.Vector(3, dt=ti.f32, shape=()) gravity = ti.Vector(3, dt=ti.f32, shape=()) collisionC = ti.Vector(3, dt=ti.f32, shape=()) mass = ti.var(dt=ti.i32, shape=()) damping = ti.var(dt=ti.i32, shape=()) pointSize = ti.var(dt=ti.i32, shape=()) deltaT = ti.var(dt=ti.f32, shape=()) KsStruct = ti.var(dt=ti.f32, shape=()) KdStruct = ti.var(dt=ti.f32, shape=()) KsShear = ti.var(dt=ti.f32, shape=())
def test_python_scope_matrix_operations(): for ops in operation_types: a, b = test_matrix_arrays[:2] m1, m2 = ti.Matrix(a), ti.Matrix(b) c = ops(m1, m2) assert np.allclose(c.to_numpy(), ops(a, b))
def M33(mat): return ti.Matrix([[mat[i, j] for j in range(3)] for i in range(3)])
import math as math ti.init(debug=False, arch=ti.cpu) real = ti.f32 #data type f32 -> float in C max_num_particles = 1000 lambda_epsilon = 0.0 #user specified relaxation parameter(important) -> adjustable dt = 1e-2 #simulation time step(important) -> adjustable dt_inv = 1 / dt dx = 0.02 dim = 2 pbd_num_iters = 30 #Iteration number(important) -> adjustable scalar = lambda: ti.var(dt=real) #2D dense tensor vec = lambda: ti.Vector(dim, dt=real) #2*1 vector(each element in a tensor) mat = lambda: ti.Matrix(dim, dim, dt=real ) #2*2 matrix(each element in a tensor) num_particles = ti.var(ti.i32, shape=()) paused = ti.var(ti.i32, shape=()) damping = ti.var(ti.f32, shape=()) particle_mass = 1 #mi particle_mass_inv = 1 / particle_mass # 1 / mi particle_mass_invv = 1 / (particle_mass_inv + particle_mass_inv + lambda_epsilon) maximum_constraints = 50 bottom_y = 0.05 bottom_x = 0.95 epsolon = 0.0001 #digit accurary(important) -> adjustable
def foo(i: ti.i32, ref: ti.template()): m = ti.Matrix([[0., 0., 0., 0.] for _ in range(3)]) vec = ti.Vector([1., 2., 3., 4.]) m[i, :] = vec.transpose() assert all(m == ref)
def test_python_scope_inplace_operator(): for ops in inplace_operation_types: a, b = test_matrix_arrays[:2] m1, m2 = ti.Matrix(a), ti.Matrix(b) m1 = ops(m1, m2) assert np.allclose(m1.to_numpy(), ops(a, b))
def updateIsotropicHelper(self, p, F): self.reinitializeIsotropicHelper(p) if ti.static(self.dim == 2): U, sigma, V = ti.svd(F) J = sigma[0, 0] * sigma[1, 1] _2mu = self.mu_0 * 2 _lambda = self.lambda_0 * (J - 1) Sprod = ti.Vector([sigma[1, 1], sigma[0, 0]]) self.psi0[p] = _2mu * (sigma[0, 0] - 1) + _lambda * Sprod[0] self.psi1[p] = _2mu * (sigma[1, 1] - 1) + _lambda * Sprod[1] self.psi00[p] = _2mu + self.lambda_0 * Sprod[0] * Sprod[0] self.psi11[p] = _2mu + self.lambda_0 * Sprod[1] * Sprod[1] self.psi01[p] = _lambda + self.lambda_0 * Sprod[0] * Sprod[1] # (psi0-psi1)/(sigma0-sigma1) self.m01[p] = _2mu - _lambda # (psi0+psi1)/(sigma0+sigma1) self.p01[p] = (self.psi0[p] + self.psi1[p]) / self.clamp_small_magnitude( sigma[0, 0] + sigma[1, 1], 1e-6) self.Aij[p] = ti.Matrix([[self.psi00[p], self.psi01[p]], [self.psi01[p], self.psi11[p]]]) self.B01[p] = ti.Matrix([[(self.m01[p] + self.p01[p]) * 0.5, (self.m01[p] - self.p01[p]) * 0.5], [(self.m01[p] - self.p01[p]) * 0.5, (self.m01[p] + self.p01[p]) * 0.5]]) # proj A self.makePD(self.Aij[p]) # proj B self.makePD2d(self.B01[p]) if ti.static(self.dim == 3): U, sigma, V = ti.svd(F) J = sigma[0, 0] * sigma[1, 1] * sigma[2, 2] _2mu = self.mu_0 * 2 _lambda = self.lambda_0 * (J - 1) Sprod = ti.Vector([ sigma[1, 1] * sigma[2, 2], sigma[0, 0] * sigma[2, 2], sigma[0, 0] * sigma[1, 1] ]) self.psi0[p] = _2mu * (sigma[0, 0] - 1) + _lambda * Sprod[0] self.psi1[p] = _2mu * (sigma[1, 1] - 1) + _lambda * Sprod[1] self.psi2[p] = _2mu * (sigma[2, 2] - 1) + _lambda * Sprod[2] self.psi00[p] = _2mu + self.lambda_0 * Sprod[0] * Sprod[0] self.psi11[p] = _2mu + self.lambda_0 * Sprod[1] * Sprod[1] self.psi22[p] = _2mu + self.lambda_0 * Sprod[2] * Sprod[2] self.psi01[p] = _lambda * sigma[ 2, 2] + self.lambda_0 * Sprod[0] * Sprod[1] self.psi02[p] = _lambda * sigma[ 1, 1] + self.lambda_0 * Sprod[0] * Sprod[2] self.psi12[p] = _lambda * sigma[ 0, 0] + self.lambda_0 * Sprod[1] * Sprod[2] # (psiA-psiB)/(sigmaA-sigmaB) self.m01[p] = _2mu - _lambda * sigma[2, 2] # i[p] = 0 self.m02[p] = _2mu - _lambda * sigma[1, 1] # i[p] = 2 self.m12[p] = _2mu - _lambda * sigma[0, 0] # i[p] = 1 # (psiA+psiB)/(sigmaA+sigmaB) self.p01[p] = (self.psi0[p] + self.psi1[p]) / self.clamp_small_magnitude( sigma[0, 0] + sigma[1, 1], 1e-6) self.p02[p] = (self.psi0[p] + self.psi2[p]) / self.clamp_small_magnitude( sigma[0, 0] + sigma[2, 2], 1e-6) self.p12[p] = (self.psi1[p] + self.psi2[p]) / self.clamp_small_magnitude( sigma[1, 1] + sigma[2, 2], 1e-6) self.Aij[p] = ti.Matrix( [[self.psi00[p], self.psi01[p], self.psi02[p]], [self.psi01[p], self.psi11[p], self.psi12[p]], [self.psi02[p], self.psi12[p], self.psi22[p]]]) self.B01[p] = ti.matrix([[(self.m01[p] + self.p01[p]) * 0.5, (self.m01[p] - self.p01[p]) * 0.5], [(self.m01[p] - self.p01[p]) * 0.5, (self.m01[p] + self.p01[p]) * 0.5]]) self.B12[p] = ti.matrix([[(self.m12[p] + self.p12[p]) * 0.5, (self.m12[p] - self.p12[p]) * 0.5], [(self.m12[p] - self.p12[p]) * 0.5, (self.m12[p] + self.p12[p]) * 0.5]]) self.B20[p] = ti.matrix([[(self.m02[p] + self.p02[p]) * 0.5, (self.m02[p] - self.p02[p]) * 0.5], [(self.m02[p] - self.p02[p]) * 0.5, (self.m02[p] + self.p02[p]) * 0.5]]) # proj A self.makePD(self.Aij[p]) # proj B self.makePD2d(self.B01[p]) self.makePD2d(self.B12[p]) self.makePD2d(self.B20[p])
def initialize(): for i in range(n_particles): v[i] = ti.Matrix([0, 0]) F[i] = ti.Matrix([[1, 0], [0, 1]]) Jp[i] = 1
import taichi as ti ti.init(arch=ti.cuda) a = ti.field(ti.f32, (42, 63)) b = ti.Vector(3, dt=ti.f32, shape=4) c = ti.Matrix(2, 2, dt=ti.f32, shape=(3, 5)) loss = ti.field(ti.f32, shape=()) a[3, 4] = 1 print(a[3, 4]) print(a) b[0] = [6, 7, 8] print(b[0][0], b[0][1], b[0][2]) loss[None] = 3 print(loss[None]) @ti.kernel def hello(i: ti.i32): a = 40 print('hello world', a + i) hello(2)
def var(n, m, dt, **kwargs): import taichi as ti return ti.Matrix(n=n, m=m, dt=dt, **kwargs)
def unit(n, i, dt=None): import taichi as ti if dt is None: dt = ti.get_runtime().default_ip assert 0 <= i < n return ti.Matrix([ti.cast(int(j == i), dt) for j in range(n)])
def empty(n, m): import taichi as ti mat = ti.Matrix([[None] * m for _ in range(n)]) return mat
def rotation2d(alpha): import taichi as ti return ti.Matrix([[ti.cos(alpha), -ti.sin(alpha)], [ti.sin(alpha), ti.cos(alpha)]])
def getRotMat2D(rotation) -> Matrix: return ti.Matrix([[ti.cos(rotation), -ti.sin(rotation)], [ti.sin(rotation), ti.cos(rotation)]])
def func(): bad = ti.Matrix([[2, 3], [4, 5]]) a[None], b[None], c[None], d[None] = bad
def rotation_matrix(r): return ti.Matrix([[ti.cos(r), -ti.sin(r)], [ti.sin(r), ti.cos(r)]])
def rotate_18_degrees(): angle = math.pi / 10 x[None] = x[None] @ ti.Matrix( [[ti.cos(angle), ti.sin(angle)], [-ti.sin(angle), ti.cos(angle)]])
write_to_disk = True ti.init(arch=ti.gpu) # Try to run on GPU. Use arch=ti.opengl on old GPUs dim = 3 quality = 1 # Use a larger value for higher-res simulations n_particles, n_grid = 1728 * quality**dim, 84 * quality dx, inv_dx = 1 / n_grid, float(n_grid) dt = 1e-4 / quality # p_vol, p_rho = ti.cast((dx * 0.5)**dim, ti.f32), ti.cast(1.4, ti.f32) # p_mass = p_vol * p_rho E, nu = 0.1e4, 0.2 # Young's modulus and Poisson's ratio mu_0, lambda_0 = E / (2 * (1 + nu)), E * nu / ( (1 + nu) * (1 - 2 * nu)) # initial Lame coefficients x = ti.Vector(dim, dt=ti.f32, shape=n_particles) # position v = ti.Vector(dim, dt=ti.f32, shape=n_particles) # velocity # C = ti.Matrix(dim, dim, dt=ti.f32, shape=n_particles) # affine velocity field F = ti.Matrix(dim, dim, dt=ti.f32, shape=n_particles) # deformation gradient Jp = ti.var(dt=ti.f32, shape=n_particles) # plastic deformation """foam attribute""" p_m = ti.var(dt=ti.f32, shape=n_particles) rho = ti.var(dt=ti.f32, shape=n_particles) vol = ti.var(dt=ti.f32, shape=n_particles) weak = ti.var(dt=ti.f32, shape=n_particles) grid_f = ti.Vector(dim, dt=ti.f32, shape=(n_grid, n_grid, n_grid)) new_grid_v = ti.Vector(dim, dt=ti.f32, shape=(n_grid, n_grid, n_grid)) f = open('0.txt', 'w') """foam attribute""" """foam var""" gravity = -10 kappa = 109.0 mu = 11.2 yield_stress = 0.1
import random dim = 2 n_particles = 8192 n_grid = 128 dx = 1 / n_grid inv_dx = 1 / dx dt = 2.0e-4 p_vol = (dx * 0.5) ** 2 p_rho = 1 p_mass = p_vol * p_rho E = 400 x = ti.Vector(dim, dt=ti.f32, shape=n_particles) v = ti.Vector(dim, dt=ti.f32, shape=n_particles) C = ti.Matrix(dim, dim, dt=ti.f32, shape=n_particles) J = ti.var(dt=ti.f32, shape=n_particles) grid_v = ti.Vector(dim, dt=ti.f32, shape=(n_grid, n_grid)) grid_m = ti.var(dt=ti.f32, shape=(n_grid, n_grid)) ti.cfg.arch = ti.cuda @ti.kernel def substep(): for p in x: base = (x[p] * inv_dx - 0.5).cast(int) fx = x[p] * inv_dx - base.cast(float) w = [0.5 * ti.sqr(1.5 - fx), 0.75 - ti.sqr(fx - 1), 0.5 * ti.sqr(fx - 0.5)] stress = -dt * p_vol * (J[p] - 1) * 4 * inv_dx * inv_dx * E
import taichi as ti import numpy as np ti.init(arch=ti.gpu) # Try to run on GPU quality = 1 # Use a larger value for higher-res simulations n_particles, n_grid = 9000 * quality**2, 128 * quality dx, inv_dx = 1 / n_grid, float(n_grid) dt = 1e-4 / quality p_vol, p_rho = (dx * 0.5)**2, 1 p_mass = p_vol * p_rho E, nu = 0.1e4, 0.2 # Young's modulus and Poisson's ratio mu_0, lambda_0 = E / (2 * (1 + nu)), E * nu / ( (1 + nu) * (1 - 2 * nu)) # Lame parameters x = ti.Vector(2, dt=ti.f32, shape=n_particles) # position v = ti.Vector(2, dt=ti.f32, shape=n_particles) # velocity C = ti.Matrix(2, 2, dt=ti.f32, shape=n_particles) # affine velocity field F = ti.Matrix(2, 2, dt=ti.f32, shape=n_particles) # deformation gradient material = ti.var(dt=ti.i32, shape=n_particles) # material id Jp = ti.var(dt=ti.f32, shape=n_particles) # plastic deformation grid_v = ti.Vector(2, dt=ti.f32, shape=(n_grid, n_grid)) # grid node momentum/velocity grid_m = ti.var(dt=ti.f32, shape=(n_grid, n_grid)) # grid node mass @ti.kernel def substep(): for i, j in grid_m: grid_v[i, j] = [0, 0] grid_m[i, j] = 0 for p in x: # Particle state update and scatter to grid (P2G) base = (x[p] * inv_dx - 0.5).cast(int)
def zero(dt, n, m=1): import taichi as ti return ti.Matrix([[ti.cast(0, dt) for _ in range(m)] for _ in range(n)])
def __init__(self): self.trans = ti.Matrix(3, 3, ti.f32, ()) self.pos = ti.Vector(3, ti.f32, ()) self.type = self.TAN_FOV self.fov = 25