示例#1
0
def paint():
    for i, j in ti.ndrange(n, n):
        t = x[i, j]
        block1_index = ti.rescale_index(x, block1, [i, j])
        block2_index = ti.rescale_index(x, block2, [i, j])
        block3_index = ti.rescale_index(x, block3, [i, j])
        t += ti.is_active(block1, block1_index)
        t += ti.is_active(block2, block2_index)
        t += ti.is_active(block3, block3_index)
        img[scatter(i), scatter(j)] = 1 - t / 4
示例#2
0
 def g2p(self, dt: ti.f32):
     ti.block_dim(256)
     if ti.static(self.use_bls):
         for d in ti.static(range(self.dim)):
             ti.block_local(self.grid_v.get_scalar_field(d))
     ti.no_activate(self.particle)
     for I in ti.grouped(self.pid):
         p = self.pid[I]
         base = ti.floor(self.x[p] * self.inv_dx - 0.5).cast(int)
         Im = ti.rescale_index(self.pid, self.grid_m, I)
         for D in ti.static(range(self.dim)):
             base[D] = ti.assume_in_range(base[D], Im[D], 0, 1)
         fx = self.x[p] * self.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, self.dim)
         new_C = ti.Matrix.zero(ti.f32, self.dim, self.dim)
         # Loop over 3x3 grid node neighborhood
         for offset in ti.static(ti.grouped(self.stencil_range())):
             dpos = offset.cast(float) - fx
             g_v = self.grid_v[base + offset]
             weight = 1.0
             for d in ti.static(range(self.dim)):
                 weight *= w[offset[d]][d]
             new_v += weight * g_v
             new_C += 4 * self.inv_dx * weight * g_v.outer_product(dpos)
         if self.material[p] != self.material_stationary:
             self.v[p], self.C[p] = new_v, new_C
             self.x[p] += dt * self.v[p]  # advection
示例#3
0
def sparse_api_demo():
    ti.activate(block1, [0, 1])
    ti.activate(block2, [1, 2])

    for i, j in x:
        print('field x[{}, {}] = {}'.format(i, j, x[i, j]))
    # outputs:
    # field x[2, 4] = 0
    # field x[2, 5] = 0
    # field x[3, 4] = 0
    # field x[3, 5] = 0

    for i, j in block2:
        print('Active block2: [{}, {}]'.format(i, j))
    # output: Active block2: [1, 2]

    for i, j in block1:
        print('Active block1: [{}, {}]'.format(i, j))
    # output: Active block1: [0, 1]

    for j in range(4):
        print('Activity of block2[2, {}] = {}'.format(
            j, ti.is_active(block2, [1, j])))

    ti.deactivate(block2, [1, 2])

    for i, j in block2:
        print('Active block2: [{}, {}]'.format(i, j))
    # output: nothing

    for i, j in block1:
        print('Active block1: [{}, {}]'.format(i, j))
    # output: Active block1: [0, 1]

    print(ti.rescale_index(x, block1, ti.Vector([9, 17])))
    # output = [2, 4]

    # Note: ti.Vector is optional in ti.rescale_index.
    print(ti.rescale_index(x, block1, [9, 17]))
    # output = [2, 4]

    ti.activate(block2, [1, 2])
示例#4
0
 def insert():
     ti.block_dim(256)
     for i in x:
         # It is important to ensure insert and p2g uses the exact same way to compute the base
         # coordinates. Otherwise there might be coordinate mismatch due to float-point errors.
         base = ti.Vector([
             int(ti.floor(x[i][0] * N) - grid_offset[0]),
             int(ti.floor(x[i][1] * N) - grid_offset[1])
         ])
         base_p = ti.rescale_index(m1, pid, base)
         ti.append(pid.parent(), base_p, i)
示例#5
0
 def build_pid(self, pid: ti.template(), grid_m: ti.template(), offset: ti.template()):
     """
     grid has blocking (e.g. 4x4x4), we wish to put the particles from each block into a GPU block,
     then used shared memory (ti.block_local) to accelerate
     :param pid:
     :param grid_m:
     :param offset:
     :return:
     """
     ti.block_dim(64)
     for p in self.x:
         base = int(ti.floor(self.x[p] * self.inv_dx - 0.5)) \
                - ti.Vector(list(self.offset))
         # pid grandparent is `block`
         base_pid = ti.rescale_index(grid_m, pid.parent(2), base)
         ti.append(pid.parent(), base_pid, p)
示例#6
0
    def p2g(use_shared: ti.template(), m: ti.template()):
        ti.block_dim(256)
        if ti.static(use_shared):
            ti.block_local(m)
        for I in ti.grouped(pid):
            p = pid[I]

            u_ = ti.floor(x[p] * N).cast(ti.i32)
            Im = ti.rescale_index(pid, m, I)
            u0 = ti.assume_in_range(u_[0], Im[0], 0, 1)
            u1 = ti.assume_in_range(u_[1], Im[1], 0, 1)

            u = ti.Vector([u0, u1])

            for offset in ti.static(ti.grouped(ti.ndrange(extend, extend))):
                m[u + offset] += scatter_weight
示例#7
0
    def g2p(use_shared: ti.template(), s: ti.template()):
        ti.block_dim(256)
        if ti.static(use_shared):
            ti.block_local(m1)
        for I in ti.grouped(pid):
            p = pid[I]

            u_ = ti.floor(x[p] * N).cast(ti.i32)

            Im = ti.rescale_index(pid, m1, I)
            u0 = ti.assume_in_range(u_[0], Im[0], 0, 1)
            u1 = ti.assume_in_range(u_[1], Im[1], 0, 1)

            u = ti.Vector([u0, u1])

            tot = 0.0

            for offset in ti.static(ti.grouped(ti.ndrange(extend, extend))):
                tot += m1[u + offset]

            s[p] = tot
示例#8
0
    def p2g(self, dt: ti.f32):
        ti.no_activate(self.particle)
        ti.block_dim(256)
        if ti.static(self.use_bls):
            for d in ti.static(range(self.dim)):
                ti.block_local(self.grid_v.get_scalar_field(d))
            ti.block_local(self.grid_m)
        for I in ti.grouped(self.pid):
            p = self.pid[I]
            base = ti.floor(self.x[p] * self.inv_dx - 0.5).cast(int)
            Im = ti.rescale_index(self.pid, self.grid_m, I)
            for D in ti.static(range(self.dim)):
                # For block shared memory: hint compiler that there is a connection between `base` and loop index `I`
                base[D] = ti.assume_in_range(base[D], Im[D], 0, 1)

            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 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]
            # Deformation gradient update
            F = self.F[p]
            if self.material[p] == self.material_water:  # liquid
                F = ti.Matrix.identity(ti.f32, self.dim)
                if ti.static(self.support_plasticity):
                    F[0, 0] = self.Jp[p]

            F = (ti.Matrix.identity(ti.f32, self.dim) + dt * self.C[p]) @ F
            # Hardening coefficient: snow gets harder when compressed
            h = 1.0
            if ti.static(self.support_plasticity):
                if self.material[p] != self.material_water:
                    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(F)
            J = 1.0
            if self.material[p] != self.material_sand:
                for d in ti.static(range(self.dim)):
                    new_sig = sig[d, d]
                    if self.material[p] == self.material_snow:  # Snow
                        new_sig = min(max(sig[d, d], 1 - 2.5e-2),
                                      1 + 4.5e-3)  # Plasticity
                    if ti.static(self.support_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
                F = ti.Matrix.identity(ti.f32, self.dim)
                F[0, 0] = J
                if ti.static(self.support_plasticity):
                    self.Jp[p] = J
            elif self.material[p] == self.material_snow:
                # Reconstruct elastic deformation gradient after plasticity
                F = U @ sig @ V.transpose()

            stress = ti.Matrix.zero(ti.f32, self.dim, self.dim)

            if self.material[p] != self.material_sand:
                stress = 2 * mu * (F - U @ V.transpose()) @ F.transpose(
                ) + ti.Matrix.identity(ti.f32, self.dim) * la * J * (J - 1)
            else:
                if ti.static(self.support_plasticity):
                    sig = self.sand_projection(sig, p)
                    F = U @ sig @ V.transpose()
                    log_sig_sum = 0.0
                    center = ti.Matrix.zero(ti.f32, self.dim, self.dim)
                    for i in ti.static(range(self.dim)):
                        log_sig_sum += ti.log(sig[i, i])
                        center[i, i] = 2.0 * self.mu_0 * ti.log(
                            sig[i, i]) * (1 / sig[i, i])
                    for i in ti.static(range(self.dim)):
                        center[i,
                               i] += self.lambda_0 * log_sig_sum * (1 /
                                                                    sig[i, i])
                    stress = U @ center @ V.transpose() @ F.transpose()
            self.F[p] = F

            stress = (-dt * self.p_vol * 4 * self.inv_dx**2) * stress
            # TODO: implement g2p2g pmass
            mass = self.p_mass
            if self.material[p] == self.material_water:
                mass *= self.water_density
            affine = stress + 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 * (mass * self.v[p] +
                                                        affine @ dpos)
                self.grid_m[base + offset] += weight * mass
示例#9
0
    def g2p2g(self, dt: ti.f32, pid: ti.template(), grid_v_in: ti.template(),
              grid_v_out: ti.template(), grid_m_out: ti.template()):
        ti.block_dim(256)
        ti.no_activate(self.particle)
        if ti.static(self.use_bls):
            ti.block_local(grid_m_out)
            for d in ti.static(range(self.dim)):
                ti.block_local(grid_v_in.get_scalar_field(d))
                ti.block_local(grid_v_out.get_scalar_field(d))
        for I in ti.grouped(pid):
            p = pid[I]
            # G2P
            base = ti.floor(self.x[p] * self.inv_dx - 0.5).cast(int)
            Im = ti.rescale_index(pid, grid_m_out, I)
            for D in ti.static(range(self.dim)):
                base[D] = ti.assume_in_range(base[D], Im[D], 0, 1)
            fx = self.x[p] * self.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, self.dim)
            C = ti.Matrix.zero(ti.f32, self.dim, self.dim)
            # Loop over 3x3 grid node neighborhood
            for offset in ti.static(ti.grouped(self.stencil_range())):
                dpos = offset.cast(float) - fx
                g_v = grid_v_in[base + offset]
                weight = 1.0
                for d in ti.static(range(self.dim)):
                    weight *= w[offset[d]][d]
                new_v += weight * g_v
                C += 4 * self.inv_dx * weight * g_v.outer_product(dpos)

            if p >= self.last_time_final_particles[None]:
                # New particles. No G2P.
                new_v = self.v[p]
                C = ti.Matrix.zero(ti.f32, self.dim, self.dim)

            if self.material[p] != self.material_stationary:
                self.v[p] = new_v
                self.x[p] += dt * self.v[p]  # advection

            # P2G
            base = ti.floor(self.x[p] * self.inv_dx - 0.5).cast(int)
            for D in ti.static(range(self.dim)):
                base[D] = ti.assume_in_range(base[D], Im[D], -1, 2)

            fx = self.x[p] * self.inv_dx - base.cast(float)
            # Quadratic kernels  [http://mpm.graphics   Eqn. 123, with x=fx, fx-1,fx-2]
            w2 = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]
            # Deformation gradient update
            new_F = (ti.Matrix.identity(ti.f32, self.dim) + dt * C) @ self.F[p]
            if ti.static(self.quant):
                new_F = max(-self.F_bound, min(self.F_bound, new_F))
            self.F[p] = new_F
            # Hardening coefficient: snow gets harder when compressed
            h = 1.0
            if ti.static(self.support_plasticity):
                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
            if self.material[p] != self.material_sand:
                for d in ti.static(range(self.dim)):
                    new_sig = sig[d, d]
                    if self.material[p] == self.material_snow:  # Snow
                        new_sig = min(max(sig[d, d], 1 - 2.5e-2),
                                      1 + 4.5e-3)  # Plasticity
                    if ti.static(self.support_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.transpose()

            stress = ti.Matrix.zero(ti.f32, self.dim, self.dim)

            if self.material[p] != self.material_sand:
                stress = 2 * mu * (
                    self.F[p] - U @ V.transpose()) @ self.F[p].transpose(
                    ) + ti.Matrix.identity(ti.f32, self.dim) * la * J * (J - 1)
            else:
                if ti.static(self.support_plasticity):
                    sig = self.sand_projection(sig, p)
                    self.F[p] = U @ sig @ V.transpose()
                    log_sig_sum = 0.0
                    center = ti.Matrix.zero(ti.f32, self.dim, self.dim)
                    for i in ti.static(range(self.dim)):
                        log_sig_sum += ti.log(sig[i, i])
                        center[i, i] = 2.0 * self.mu_0 * ti.log(
                            sig[i, i]) * (1 / sig[i, i])
                    for i in ti.static(range(self.dim)):
                        center[i,
                               i] += self.lambda_0 * log_sig_sum * (1 /
                                                                    sig[i, i])
                    stress = U @ center @ V.transpose() @ self.F[p].transpose()

            stress = (-dt * self.p_vol * 4 * self.inv_dx**2) * stress
            affine = stress + self.p_mass * C

            # 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 *= w2[offset[d]][d]
                grid_v_out[base +
                           offset] += weight * (self.p_mass * self.v[p] +
                                                affine @ dpos)
                grid_m_out[base + offset] += weight * self.p_mass

        self.last_time_final_particles[None] = self.n_particles[None]
示例#10
0
 def set_a():
     for I in ti.grouped(b):
         Ia = ti.rescale_index(b, a, I)
         a[Ia] = 1.0
示例#11
0
 def set_b():
     for I in ti.grouped(a):
         Ib = ti.rescale_index(a, b, I)
         b[Ib] += 1.0