Beispiel #1
0
 def copy(bls: ti.template(), w: ti.template()):
     if ti.static(bls):
         ti.cache_shared(x, y, z)
     for i, j in x:
         w[i,
           j] = x[i, j - 2] + y[i + 2, j -
                                1] + y[i - 1, j] + z[i - 1, j] + z[i + 1, j]
Beispiel #2
0
 def g2p(self, dt: ti.f32):
     ti.block_dim(256)
     ti.cache_shared(*self.grid_v.entries)
     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)
         for D in ti.static(range(self.dim)):
             base[D] = ti.assume_in_range(base[D], I[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)
         self.v[p], self.C[p] = new_v, new_C
         self.x[p] += dt * self.v[p]  # advection
Beispiel #3
0
    def p2g(use_shared: ti.template(), m: ti.template()):
        ti.block_dim(256)
        if ti.static(use_shared):
            ti.cache_shared(m)
        for i, j, l in pid:
            p = pid[i, j, l]

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

            u0 = ti.assume_in_range(u_[0], i, 0, 1)
            u1 = ti.assume_in_range(u_[1], j, 0, 1)

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

            for offset in ti.static(ti.grouped(ti.ndrange(extend, extend))):
                m[u + offset] += scatter_weight
Beispiel #4
0
    def apply(use_bls: ti.template(), y: ti.template()):
        if ti.static(use_bls and not scatter):
            ti.cache_shared(x)
        if ti.static(use_bls and scatter):
            ti.cache_shared(y)

        ti.block_dim(block_dim)
        for I in ti.grouped(x):
            if ti.static(scatter):
                for offset in ti.static(stencil):
                    y[I + ti.Vector(offset)] += x[I]
            else:
                # gather
                s = 0
                for offset in ti.static(stencil):
                    s = s + x[I + ti.Vector(offset)]
                y[I] = s
Beispiel #5
0
    def g2p(use_shared: ti.template(), s: ti.template()):
        ti.block_dim(256)
        if ti.static(use_shared):
            ti.cache_shared(m1)
        for i, j, l in pid:
            p = pid[i, j, l]

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

            u0 = ti.assume_in_range(u_[0], i, 0, 1)
            u1 = ti.assume_in_range(u_[1], j, 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
Beispiel #6
0
 def copy():
     ti.cache_shared(x)
     for i, j in x:
         y[i, j] = x[i, j]
Beispiel #7
0
 def copy():
     ti.cache_shared(x)
     for i in x:
         y[i] = x[i]
Beispiel #8
0
    def p2g(self, dt: ti.f32):
        ti.no_activate(self.particle)
        ti.block_dim(256)
        ti.cache_shared(*self.grid_v.entries)
        ti.cache_shared(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)
            for D in ti.static(range(self.dim)):
                base[D] = ti.assume_in_range(base[D], I[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
            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
            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
                    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 = ti.Matrix.zero(ti.f32, self.dim, self.dim)

            if self.material[p] != self.material_sand:
                stress = 2 * mu * (self.F[p] - U @ V.T()) @ self.F[p].T(
                ) + ti.Matrix.identity(ti.f32, self.dim) * la * J * (J - 1)
            else:
                sig = self.sand_projection(sig, p)
                self.F[p] = U @ sig @ V.T()
                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.T() @ self.F[p].T()

            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