Beispiel #1
0
def apply_impulse(vf: ti.types.ndarray(field_dim=2),
                  dyef: ti.types.ndarray(field_dim=2),
                  imp_data: ti.types.ndarray(field_dim=1)):
    g_dir = -ti.Vector([0, 9.8]) * 300
    for i, j in vf:
        omx, omy = imp_data[2], imp_data[3]
        mdir = ti.Vector([imp_data[0], imp_data[1]])
        dx, dy = (i + 0.5 - omx), (j + 0.5 - omy)
        d2 = dx * dx + dy * dy
        # dv = F * dt
        factor = ti.exp(-d2 / force_radius)

        dc = dyef[i, j]
        a = dc.norm()

        momentum = (mdir * f_strength * factor + g_dir * a / (1 + a)) * dt

        v = vf[i, j]
        vf[i, j] = v + momentum
        # add dye
        if mdir.norm() > 0.5:
            dc += ti.exp(-d2 * (4 / (res / 15)**2)) * ti.Vector(
                [imp_data[4], imp_data[5], imp_data[6]])

        dyef[i, j] = dc
Beispiel #2
0
def mainImage(iMouse: ti.Vector, iTime: ti.f32, i: ti.i32,
              j: ti.i32) -> ti.Vector:
    fragCoord = ti.Vector([i, j])

    p = -1.0 + 2.0 * fragCoord / iResolution
    m = -1.0 + 2.0 * iMouse  # iMouse 已经归一化

    a1 = ti.atan2(p[1] - m[1], p[0] - m[0])
    a2 = ti.atan2(p[1] + m[1], p[0] + m[0])
    r1 = ti.sqrt((p - m).dot(p - m))
    r2 = ti.sqrt((p + m).dot(p + m))

    uv = ti.Vector(
        [0.2 * iTime + (r1 - r2) * 0.25,
         ti.asin(ti.sin(a1 - a2)) / 3.1416])

    w = ti.exp(-15.0 * r1 * r1) + ti.exp(-15.0 * r2 * r2)
    w += 0.25 * smoothstep(0.93, 1.0, ti.sin(128.0 * uv[0]))
    w += 0.25 * smoothstep(0.93, 1.0, ti.sin(128.0 * uv[1]))

    # 可以使用纹理
    # vec3 col = texture( iChannel0, 0.125*uv ).zyx;
    col = ti.Vector([0.0, 0.0, 0.0])
    fragColor = col + w
    return fragColor
    def apply_mouse_input_and_render(self, vf: ti.template(),
                                     dyef: ti.template(),
                                     imp_data: ti.ext_arr(),
                                     dt: ti.template()):

        for i, j in vf:
            mdir = ti.Vector([imp_data[0], imp_data[1]])
            omx, omy = imp_data[2], imp_data[3]
            # move to cell center
            dx, dy = (i + 0.5 - omx), (j + 0.5 - omy)
            d2 = dx * dx + dy * dy
            # ref: https://developer.download.nvidia.cn/books/HTML/gpugems/gpugems_ch38.html
            # apply the force
            factor = ti.exp(-d2 * self.cfg.inv_force_radius)
            momentum = mdir * self.cfg.f_strength * dt * factor

            vf[i, j] += momentum
            # add dye
            dc = dyef[i, j]
            # TODO what the hell is this?
            if mdir.norm() > 0.5:
                dc += ti.exp(-d2 * self.cfg.inv_dye_denom) * ti.Vector(
                    [imp_data[4], imp_data[5], imp_data[6]])
            dc *= self.cfg.dye_decay
            dyef[i, j] = dc
Beispiel #4
0
def initialize_vortices():
    for i, j in ux:
        s = 0.16
        x = xCoord(i) * 2.0
        y = yCoord(j) * 2.0
        x0 = x - s
        x1 = x + s
        ux_ = 0.0
        uy_ = 0.0

        # add vortex
        rr1 = sq(x0) + sq(y)
        ux_ += -y * ti.exp(-rr1 / (2.0 * sq(0.12))) * 25.0
        uy_ += x0 * ti.exp(-rr1 / (2.0 * sq(0.12))) * 25.0
        # add vortex
        rr2 = sq(x1) + sq(y)
        ux_ += -y * ti.exp(-rr2 / (2.0 * sq(0.12))) * 25.0
        uy_ += x1 * ti.exp(-rr2 / (2.0 * sq(0.12))) * 25.0

        ux[i, j] = ux_
        uy[i, j] = uy_

    for i, j in omega:
        i_p = mod(i + 1, Nx)
        i_n = mod(i - 1 + Nx, Nx)
        j_p = mod(j + 1, Ny)
        j_n = mod(j - 1 + Ny, Ny)

        omega[i, j] = \
            (uy[i_p, j] - uy[i_n, j]) / (2.0 * dx) \
            - (ux[i, j_p] - ux[i, j_n]) / (2.0 * dx)
def apply_force(velocities:ti.template(), colors:ti.template(), collisons:ti.template(), imp_data: ti.ext_arr()):

	f_strength = 10000.0
	force_radius = n / 3.0
	for i, j in velocities:
		omx, omy = imp_data[2], imp_data[3]
		mdir = ti.Vector([imp_data[0], imp_data[1]])
		dx, dy = (i + 0.5 - omx), (j + 0.5 - omy)
		d2 = dx * dx + dy * dy
		# dv = F * dt
		factor = ti.exp(-d2 / force_radius)
		momentum = mdir * f_strength * dt * factor
		v = velocities[i, j]
		velocities[i, j] = v + momentum
		# add dye
		color = ti.Vector([1.0, 1.0, 1.0])
		dc = colors[i, j]
		if mdir.norm() > 0.5:
			# dc += ti.exp(-d2 * (4 / (n / 15)**2)) * ti.Vector([imp_data[4], imp_data[5], imp_data[6]])
			dc += ti.exp(-d2 * (4 / (n / 15)**2)) * color
		dc *= dye_decay
		colors[i, j] = dc

		if mdir.norm() > 0.5 and d2 < 50:
			collisons[i, j] = 1
Beispiel #6
0
def substep():
    # 计算力和新的速度
    # Compute force and new velocity
    n = num_particles[None]
    for i in range(n-1, -1, -1):
        v[i] *= ti.exp(-dt * damping[None])  # damping
        total_force = ti.Vector(gravity) * particle_mass  # 初始受力只有重力
        for j in range(n):
            # 对于互相连接的粒子用胡克定律计算力
            if rest_length[i, j] != 0:
                x_ij = x[i] - x[j]
                total_force += -spring_stiffness[None] * (
                    x_ij.norm() -
                    rest_length[i, j]) * x_ij.normalized()  # 加上弹簧之间的力
        v[i] += dt * total_force / particle_mass  # 牛顿第二定律

    # 碰撞地面
    # Collide with ground
    for i in range(n):
        if x[i].y < bottom_y:
            x[i].y = bottom_y
            v[i].y = 0

    # 计算新的位置
    # Compute new position
    for i in range(num_particles[None]):
        x[i] += v[i] * dt
Beispiel #7
0
 def init_level_set(self):
     sdf = ti.static(self.sign_dis.curr)
     inv_r = ti.static(4.0 / (self.resolution / 20.0)**2)
     for i, j in sdf:
         dx, dy = self.resolution / 2 - i, j
         d2 = dx * dx + dy * dy
         sdf[i, 0] = ti.exp(-d2 * inv_r) * 10.0
Beispiel #8
0
    def collide(self, f, grid_pos, v_out, dt):
        dist = self.sdf(f, grid_pos)
        influence = min(ti.exp(-dist * self.softness[None]), 1)
        if (self.softness[None] > 0 and influence > 0.1) or dist <= 0:
            D = self.normal(f, grid_pos)
            collider_v_at_grid = self.collider_v(f, grid_pos, dt)

            input_v = v_out - collider_v_at_grid
            normal_component = input_v.dot(D)

            grid_v_t = input_v - min(normal_component, 0) * D

            grid_v_t_norm = length(grid_v_t)
            grid_v_t_friction = grid_v_t / grid_v_t_norm * max(
                0, grid_v_t_norm + normal_component * self.friction[None])
            flag = ti.cast(
                normal_component < 0
                and ti.sqrt(grid_v_t.dot(grid_v_t)) > 1e-30, self.dtype)
            grid_v_t = grid_v_t_friction * flag + grid_v_t * (1 - flag)
            v_out = collider_v_at_grid + input_v * (
                1 - influence) + grid_v_t * influence

            #print(self.position[f], f)
            #print(grid_pos, collider_v, v_out, dist, self.friction, D)
            #if v_out[1] > 1000:
            #print(input_v, collider_v_at_grid, normal_component, D)

        return v_out
Beispiel #9
0
 def affine(self, i):
     self.system.F[i] = (ti.Matrix.identity(ti.f32, DIM) + self.system.dt *
                         self.system.C[i]) @ self.system.F[i]
     h = 0.3 if self.system.type[i] == 1 else ti.exp(
         10 * (1.0 - self.system.Jp[i]))
     la = self.lambda_0 * h
     U, sig, V = ti.svd(self.system.F[i])
     J = 1.0
     for d in ti.static(range(DIM)):
         new_sig = min(max(sig[d, d], 1 - 2.5e-2), 1 +
                       4.5e-3) if self.system.type[i] == 2 else sig[d, d]
         self.system.Jp[i] *= sig[d, d] / new_sig
         sig[d, d] = new_sig
         J *= new_sig
     if self.system.type[
             i] == 0:  # Reset deformation gradient to avoid numerical instability
         self.system.F[i] = ti.Matrix.identity(ti.f32, DIM)
         self.system.F[i][0, 0] = J
     elif self.system.type[i] == 2:
         self.system.F[i] = U @ sig @ V.transpose(
         )  # Reconstruct elastic deformation gradient after plasticity
     stress = ti.Matrix.identity(ti.f32, DIM) * la * J * (J - 1)
     if self.system.type[i] != 0:
         stress += 2 * self.mu_0 * h * (
             self.system.F[i] -
             U @ V.transpose()) @ self.system.F[i].transpose()
     stress = (-self.system.dt * self.vol * 4 * self.inv_dx *
               self.inv_dx) * stress
     return stress + self.mass * self.system.C[i]
def substep(cur_x: ti.f32, cur_y: ti.f32, mag: ti.f32):
    # Compute force and new velocity
    n = num_particles[None]
    for i in range(n):
        v[i] *= ti.exp(-dt * damping[None])  # damping
        i2cur = [cur_x, cur_y] - x[i]
        total_force = i2cur.normalized() * mag * particle_mass
        for j in range(n):
            if rest_length[i, j] != 0:
                x_ij = x[i] - x[j]
                total_force += -spring_stiffness[None] * (
                    x_ij.norm() - rest_length[i, j]) * x_ij.normalized()
        v[i] += dt * total_force / particle_mass

    # Collide with boundary
    for i in range(n):
        if x[i].y < bottom:
            x[i].y = bottom
            v[i].y = -v[i].y
        if x[i].y > top:
            x[i].y = top
            v[i].y = -v[i].y
        if x[i].x < bottom:
            x[i].x = bottom
            v[i].x = -v[i].x
        if x[i].x > top:
            x[i].x = top
            v[i].x = -v[i].x

    # Compute new position
    for i in range(num_particles[None]):
        x[i] += v[i] * dt
def P2G(): # Particle to grid (P2G)
    for p in x: 
        base = (x[p] * inv_dx - 0.5).cast(int)
        fx = x[p] * inv_dx - base.cast(float)
        # Bspline
        w = [0.5 * (1.5 - fx) ** 2, 0.75 - (fx - 1) ** 2, 0.5 * (fx - 0.5) ** 2]
        F[p] = (ti.Matrix.identity(float, 2) + dt * C[p]) @ F[p] # deformation gradient update
        h = max(0.1, min(5, ti.exp(10 * (1.0 - Jp[p])))) # Hardening coefficient
        mu, la = mu_0 * h, lambda_0 * h
        mu = 0.0
        U, sig, V = ti.svd(F[p])
        J = 1.0
        for d in ti.static(range(2)):
            new_sig = sig[d, d]
            if material[p] == 2: # snow
                new_sig = min(max(sig[d, d], 1 - 2.5e-2), 1 + 4.5e-3)  # plasticity
            Jp[p] *= sig[d, d] / new_sig
            sig[d, d] = new_sig
            J *= new_sig 
        F[p] = ti.Matrix.identity(float, 2) * ti.sqrt(J) # Reset deformation gradient
        stress = 2 * mu * (F[p] - U @ V.transpose()) @ F[p].transpose() + ti.Matrix.identity(float, 2) * la * J * (J - 1)
        stress = (-dt * p_vol * 4 * inv_dx * inv_dx) * stress
        affine = stress + p_mass * C[p]
        for i, j in ti.static(ti.ndrange(3, 3)): # Loop over 3x3 grid
            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
Beispiel #12
0
def implicit():
    n = num_particles[None]
    for i, j in ti.ndrange(n, n):
        M[i, j].fill(0)
        K[i, j].fill(0)
        A[i, j].fill(0)
        b[i].fill(0)
    for i in range(n):
        M[i, i][0, 0] = particle_mass
        M[i, i][1, 1] = particle_mass
        v[i] *= ti.exp(-dt * damping[None])  # damping
    for i, j in ti.ndrange(n, n):
        if rest_length[i, j] != 0:
            x_ij = x[j] - x[i]
            I = ti.Matrix([[1, 0], [0, 1]])
            l = x_ij.norm()
            t = spring_stiffness[None] * (-I + rest_length[i, j] / l *
                                          (I - (x_ij @ x_ij.transpose() /
                                                (l * l))))
            K[i, i] += t
            K[i, j] += -t
    for i, j in ti.ndrange(n, n):
        A[i, j] = (M[i, j] - dt * dt * K[i, j])
    for i in range(n):
        b[i] = M[i, i] @ v[i] + dt * ti.Vector(gravity) * particle_mass
        for j in range(n):
            if rest_length[i, j] != 0:
                x_ij = x[i] - x[j]
                b[i] += -dt * spring_stiffness[None] * (
                    x_ij.norm() - rest_length[i, j]) * x_ij.normalized()
    for i in range(n):
        solve_v[i] = v[i]
Beispiel #13
0
def addRandomForce(dt: ti.f32):
    pos_p = ti.Vector([ti.random(), ti.random()])
    F = ti.Vector([ti.random(), ti.random()]) * ti.random() * 1000.0
    # if ti.random() > 0.01:
    #     F.fill(0)
    for I in ti.grouped(u_old):
        u_old[I] += F * dt * ti.exp(-(I - pos_p).norm() / 0.1)
def substep():
    # Compute force and new velocity
    n = num_particles[None]
    for i in range(n):
        v[i] *= ti.exp(-dt * damping[None]) # damping
        total_force = ti.Vector(gravity) * particle_mass
        for j in range(n):
            if rest_length[i, j] != 0:
                x_ij = x[i] - x[j]
                total_force += -spring_stiffness[None] * (x_ij.norm() - rest_length[i, j]) * x_ij.normalized()
        v[i] += dt * total_force / particle_mass
        
    # Collide with ground
    for i in range(n):
        if x[i].y < bottom_y:
            x[i].y = bottom_y
            v[i].y = 0


    # Compute new position
    for i in range(num_particles[None]):
        x[i] += v[i] * dt

    df_ij(0,0)
    f_ij(0,0)
Beispiel #15
0
def electric_field(t: ti.f64):
    t_eff = t - t_h
    a = parameters[0] / (ti.sqrt(2 * np.pi) * parameters[1])
    w = ti.sqr(parameters[1])
    e = a * ti.exp(-ti.sqr(t_eff) /
                   (2 * w)) * (ti.sin(parameters[2] * t_eff) +
                               parameters[3] * ti.sin(parameters[4] * t_eff))
    e_field[None] = e
    grad[0] = e / parameters[0]
    grad[1] = -e / parameters[1] + e * ti.sqr(t_eff) / (parameters[1]**3)
    grad[2] = a * ti.exp(-ti.sqr(t_eff) /
                         (2 * w)) * ti.cos(parameters[2] * t_eff) * t_eff
    grad[3] = a * ti.exp(-ti.sqr(t_eff) /
                         (2 * w)) * ti.sin(parameters[4] * t_eff)
    grad[4] = a * ti.exp(-ti.sqr(t_eff) / (2 * w)) * parameters[3] * ti.cos(
        parameters[4] * t_eff) * t_eff
def paint(t:ti.f32) :

    for i, j in pixels:
        p = ti.Vector([2*i-Width, 2*j-Height])/min(Width,Height)

        #background-color
        bcol = ti.Vector([1.0,0.8,0.7-0.07*p[1]]) * (1.0-0.25*p.norm())

        #animate
        tt = mod(t, 1.5)/1.5
        ss = pow(tt, 0.2)*0.5+0.5
        ss = 1.0 + ss*0.5*ti.sin(tt*6.2831*3.0+p[1]*0.5)*ti.exp(-4.0*tt)
        p *= ti.Vector([0.5, 1.5]) + ss*ti.Vector([0.5, -0.5])  

        #shape
        p[1] -= 0.25
        a = ti.atan2(p[0], p[1]) / 3.141593
        r = p.norm()
        h = abs(a)
        d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h)

        #color
        s = 0.75 + 0.75*p[0]
        s *= 1.0 - 0.4*r
        s = 0.3 + 0.7*s
        s *= 0.5 + 0.5*pow(1.0-clamp(r/d, 0.0, 1.0), 1.0)

        hcol = ti.Vector([1.0, 0.5*r, 0.3])*s
        pixels[i,j] = mix(bcol , hcol ,smoothstep(-0.01, 0.01, d-r))
def substep():
    for i in ti.grouped(x):
        v[i] += gravity * dt

    for i in ti.grouped(x):
        force = ti.Vector([0.0, 0.0, 0.0])
        for spring_offset in ti.static(spring_offsets):
            j = i + spring_offset
            if 0 <= j[0] < n and 0 <= j[1] < n:
                x_ij = x[i] - x[j]
                v_ij = v[i] - v[j]
                d = x_ij.normalized()
                current_dist = x_ij.norm()
                original_dist = quad_size * float(i - j).norm()  # pylint: disable=no-member
                # Spring force
                force += -spring_Y * d * (current_dist / original_dist - 1)
                # Dashpot damping
                force += -v_ij.dot(d) * d * dashpot_damping * quad_size

        v[i] += force * dt

    for i in ti.grouped(x):
        v[i] *= ti.exp(-drag_damping * dt)
        offset_to_center = x[i] - ball_center[0]
        if offset_to_center.norm() <= ball_radius:
            # Velocity projection
            normal = offset_to_center.normalized()
            v[i] -= min(v[i].dot(normal), 0) * normal
        x[i] += dt * v[i]
Beispiel #18
0
def substep():
  for i, j in ti.ndrange(n_grid, n_grid):
    grid_v[i, j] = [0, 0]
    grid_m[i, j] = 0
  for p in range(n_particles): # Particle state update and scatter to grid (P2G)
    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 * ti.sqr(1.5 - fx), 0.75 - ti.sqr(fx - 1), 0.5 * ti.sqr(fx - 0.5)]
    F[p] = (ti.Matrix.identity(ti.f32, 2) + dt * C[p]) @ F[p] # deformation gradient update
    h = ti.exp(10 * (1.0 - Jp[p])) # Hardening coefficient: snow gets harder when compressed
    if material[p] == 1: # jelly, make it softer
      h = 0.3
    mu, la = mu_0 * h, lambda_0 * h
    if material[p] == 0: # liquid
      mu = 0.0
    U, sig, V = ti.svd(F[p])
    J = 1.0
    for d in ti.static(range(2)):
      new_sig = sig[d, d]
      if material[p] == 2:  # Snow
        new_sig = min(max(sig[d, d], 1 - 2.5e-2), 1 + 4.5e-3)  # Plasticity
      Jp[p] *= sig[d, d] / new_sig
      sig[d, d] = new_sig
      J *= new_sig
    if material[p] == 0:  # Reset deformation gradient to avoid numerical instability
      F[p] = ti.Matrix.identity(ti.f32, 2) * ti.sqrt(J)
    elif material[p] == 2:
      F[p] = U @ sig @ V.T() # Reconstruct elastic deformation gradient after plasticity
    stress = 2 * mu * (F[p] - U @ V.T()) @ F[p].T() + ti.Matrix.identity(ti.f32, 2) * la * J * (J - 1)
    stress = (-dt * p_vol * 4 * inv_dx * inv_dx) * stress
    affine = stress + p_mass * C[p]
    for i, j in ti.static(ti.ndrange(3, 3)): # Loop over 3x3 grid node neighborhood
      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
  for i, j in ti.ndrange(n_grid, n_grid):
    if grid_m[i, j] > 0: # No need for epsilon here
      grid_v[i, j] = (1 / grid_m[i, j]) * grid_v[i, j] # Momentum to velocity
      grid_v[i, j][1] -= dt * 50 # 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
  for p in range(n_particles): # grid to particle (G2P)
    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), 0.5 * ti.sqr(fx - 0.5)]
    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 * ti.outer_product(g_v, dpos)
    v[p], C[p] = new_v, new_C
    x[p] += dt * v[p] # advection
Beispiel #19
0
    def sample(self, dir, N, t, i, j, mat_buf, mat_id):
        next_dir    = ti.Vector([0.0, 0.0, 0.0])
        w_out       = dir
        cos_theta_i = w_out.dot(N)
        ior         = UF.get_material_ior(mat_buf, mat_id)
        eta         = ior

        probability = ti.random()   
        f_or_b      = 1.0
        R           = probability + 1.0
        extinction  = 1.0

        if (cos_theta_i > 0.0):
            N      = -N
            extinction = ti.exp(-0.1*t)
        else:
            cos_theta_i = -cos_theta_i
            eta = 1.0 /ior
            

        next_dir,suc = self.refract(w_out, N, eta)
        if suc > 0.0:
            R = self.schlick(cos_theta_i, ior)

        if (probability < R):
            next_dir = ts.reflect(w_out, N)
        else:
            f_or_b   = -1.0

        return next_dir, f_or_b*extinction
def hardening(
    dq, p
):  # The amount of hardening depends on the amount of correction that occurred due to plasticity
    q_s[p] += dq
    phi = h0 + (h1 * q_s[p] - h3) * ti.exp(-h2 * q_s[p])
    phi = phi / 180 * pi  # details in Table. 3: Friction angle phi_F and hardening parameters h0, h1, and h3 are listed in degrees for convenience
    sin_phi = ti.sin(phi)
    alpha_s[p] = ti.sqrt(2 / 3) * (2 * sin_phi) / (3 - sin_phi)
Beispiel #21
0
def test_unary():
    import time
    t = time.time()
    grad_test(lambda x: ti.sqrt(x), lambda x: np.sqrt(x))
    grad_test(lambda x: ti.exp(x), lambda x: np.exp(x))
    grad_test(lambda x: ti.log(x), lambda x: np.log(x))
    ti.core.print_profile_info()
    print("Total time {:.3f}s".format(time.time() - t))
Beispiel #22
0
 def init_gwei():
     sum = -1.0
     for i in self.gwei:
         x = i / self.radius
         y = ti.exp(-x**2)
         self.gwei[i] = y
         sum += y * 2
     for i in self.gwei:
         self.gwei[i] /= sum
Beispiel #23
0
def particle_to_grid():

    for k in particle_position:

        p = particle_position[k]
        grid = p * inv_dx
        base = int(grid - 0.5)
        fx = grid - base

        w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2,
             0.5 * (fx - 0.5)**2]  # B-spline
        # stress = -dt * 4 * E * p_vol * (particle_J[k] - 1) * (inv_dx**2)
        # affine = ti.Matrix([[stress, 0], [0, stress]]) + p_mass * particle_C[k]

        particle_F[k] = (ti.Matrix.identity(float, 2) +
                         dt * particle_C[k]) @ particle_F[k]

        # hardening coefficient
        h = ti.exp(10 * (1.0 - particle_J[k]))
        if particle_material[k] == 1:  # jelly
            h = 0.3

        mu, la = mu_0 * h, lambda_0 * h
        if particle_material[k] == 0:  # fluid
            mu = 0.0

        U, sig, V = ti.svd(particle_F[k])
        J = 1.0
        for d in ti.static(range(2)):
            new_sig = sig[d, d]
            if particle_material[k] == 2:  # snow
                new_sig = min(max(sig[d, d], 1 - 2.5e-2),
                              1 + 4.5e-3)  # plasticity
            particle_J[k] *= sig[d, d] / new_sig
            sig[d, d] = new_sig
            J *= new_sig

        if particle_material[
                k] == 0:  # Fluid: Reset deformation gradient to avoid numerical instability
            particle_F[k] = ti.Matrix.identity(float, 2) * ti.sqrt(J)
        elif particle_material[k] == 2:
            particle_F[k] = U @ sig @ V.transpose(
            )  # Snow: Reconstruct elastic deformation gradient after plasticity

        stress = 2 * mu * (particle_F[k] - U @ V.transpose()) @ particle_F[
            k].transpose() + ti.Matrix.identity(float, 2) * la * J * (J - 1)
        stress = (-dt * p_vol * 4 * inv_dx * inv_dx) * stress
        affine = stress + p_mass * particle_C[k]

        for i in ti.static(range(3)):
            for j in ti.static(range(3)):
                offset = ti.Vector([i, j])
                weight = w[i][0] * w[j][1]
                dpos = (offset - fx) * dx
                grid_velocity[base + offset] += weight * (
                    p_mass * particle_velocity[k] + affine @ dpos)
                grid_weight[base + offset] += weight * p_mass
Beispiel #24
0
def accel(v: ti.template(), x: ti.template(), dt):
    for i in ti.grouped(x):
        acc = x[i] * 0
        for d in ti.static(links):
            disp = x[tl.clamp(i + d, 0, tl.vec(*NN) - 1)] - x[i]
            dis = disp.norm()
            acc += disp * (dis - L) / L**2
        v[i] += stiff * acc * dt
        v[i] *= ti.exp(-damp * dt)
Beispiel #25
0
 def init_wei():
     total = -1.0
     for i in self.wei:
         x = i / self.radius
         r = ti.exp(-x**2)
         self.wei[i] = r
         total += r * 2
     for i in self.wei:
         self.wei[i] /= total
Beispiel #26
0
def substep(n: ti.i32, t: ti.i32):  # Compute force and new velocity
    for i in range(n):
        v[i] *= ti.exp(-dt * damping[None])  # damping
        total_force = ti.Vector(
            gravity) * particle_mass  #gravity -> accelaration
        if actuation_type[i] == 1:
            #total_force = ti.Vector([9.8 * t, 0], real) * particle_mass
            total_force = ti.Vector(H_force) * particle_mass
        v[i] += dt * total_force / particle_mass
Beispiel #27
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)
Beispiel #28
0
def sampleScattering(u: ti.f32, maxDistance: ti.f32):
    # remap u to account for finite max distance
    ## f32
    minU = ti.exp(-SIGMA * maxDistance)
    a = u * (1.0 - minU) + minU

    # sample with pdf proportional to exp(-sig*d)
    dist = -ti.log(a) / SIGMA
    pdf = SIGMA * a / (1.0 - minU)
    return (dist, pdf)
Beispiel #29
0
def apply_impulse(vf: ti.template(), dyef: ti.template(),
                  imp_data: ti.ext_arr()):
    for i, j in vf:
        omx, omy = imp_data[2], imp_data[3]
        mdir = ti.Vector([imp_data[0], imp_data[1]])
        dx, dy = (i + 0.5 - omx), (j + 0.5 - omy)
        d2 = dx * dx + dy * dy
        # dv = F * dt
        factor = ti.exp(-d2 / force_radius)
        momentum = mdir * f_strength * dt * factor
        v = vf[i, j]
        vf[i, j] = v + momentum
        # add dye
        dc = dyef[i, j]
        if mdir.norm() > 0.5:
            dc += ti.exp(-d2 * (4 / (res / 15)**2)) * ti.Vector(
                [imp_data[4], imp_data[5], imp_data[6]])
        dc *= dye_decay
        dyef[i, j] = dc
Beispiel #30
0
    def p2g(self, dt: ti.f32):
        for p in self.x:
            base = (self.x[p] * self.inv_dx - 0.5).cast(int)
            fx = self.x[p] * self.inv_dx - base.cast(float)
            # Quadratic kernels  [http://mpm.graphics   Eqn. 123, with x=fx, fx-1,fx-2]
            w = [
                0.5 * ti.sqr(1.5 - fx), 0.75 - ti.sqr(fx - 1),
                0.5 * ti.sqr(fx - 0.5)
            ]
            # deformation gradient update
            self.F[p] = (ti.Matrix.identity(ti.f32, self.dim) +
                         dt * self.C[p]) @ self.F[p]
            # Hardening coefficient: snow gets harder when compressed
            h = ti.exp(10 * (1.0 - self.Jp[p]))
            if self.material[
                    p] == self.material_elastic:  # jelly, make it softer
                h = 0.3
            mu, la = self.mu_0 * h, self.lambda_0 * h
            if self.material[p] == self.material_water:  # liquid
                mu = 0.0
            U, sig, V = ti.svd(self.F[p])
            J = 1.0
            for d in ti.static(range(self.dim)):
                new_sig = sig[d, d]
                #section 7 of snow paper ... dt being too big
                if self.material[p] == self.material_snow:  # Snow
                    new_sig = min(max(sig[d, d], 1 - 2.5e-2),
                                  1 + 4.5e-3)  # Plasticity
                self.Jp[p] *= sig[d, d] / new_sig
                sig[d, d] = new_sig
                J *= new_sig
            if self.material[p] == self.material_water:
                # Reset deformation gradient to avoid numerical instability
                new_F = ti.Matrix.identity(ti.f32, self.dim)
                new_F[0, 0] = J
                self.F[p] = new_F
            elif self.material[p] == self.material_snow:
                # Reconstruct elastic deformation gradient after plasticity
                self.F[p] = U @ sig @ V.T()

            stress = 2 * mu * (self.F[p] - U @ V.T()) @ self.F[p].T(
            ) + ti.Matrix.identity(ti.f32, self.dim) * la * J * (J - 1)
            stress = (-dt * self.p_vol * 4 * self.inv_dx**2) * stress
            affine = stress + self.p_mass * self.C[p]

            # Loop over 3x3 grid node neighborhood
            for offset in ti.static(ti.grouped(self.stencil_range())):
                dpos = (offset.cast(float) - fx) * self.dx
                weight = 1.0
                for d in ti.static(range(self.dim)):
                    weight *= w[offset[d]][d]
                self.grid_v[base +
                            offset] += weight * (self.p_mass * self.v[p] +
                                                 affine @ dpos)
                self.grid_m[base + offset] += weight * self.p_mass