程序报错:AssertionError: The 0-th index of a Matrix/Vector must be a compile-time constant integer, got <taichi.lang.expr.Expr object at 0x000001ADF8191160>

Hello!我写了一个简单的函数,输入四个Vector,然后输出一个Matrix。然而在给Matrix元素赋值的步骤报错如下。代码附在了后面。似乎是40行这一步,k[2 * i, 2 * j]的index有一些问题。请问应该如何修改?谢谢!
另外,我这个函数k_ele()目的是在kernel里结构for循环中建立一个8*8矩阵。请问有没有什么更好的方法实现?谢谢!


代码:



import taichi as ti
import numpy as np

ti.init(arch = ti.gpu)

# material parameters
nu = 0.3 #Poisson's ratio
l = 8.0 #length

# simulation parameters
n_no_x = 3 #no. of nodes in x direction
n_no_y = 2 #no. of nodes in y direction
n_no = n_no_x * n_no_y
n_no_active = (n_no_x - 1) * n_no_y #excluding Dirichlet nodes

ele = ti.Vector(4, dt = ti.i32, shape = (n_no_y - 1, n_no_x - 1)) #connectivity matrix
init_pos = ti.var(dt = ti.f32, shape = n_no * 2) # store initial node position (not updated for infinitesimal deformation)


@ti.func
def k_ele(x0, x1, x2, x3):
    l_x = ti.Vector([-1, 1, 1, -1])
    l_y = ti.Vector([-1, -1, 1, 1])
    k = ti.Matrix([[0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0]])

    a = (x1[0] - x0[0]) / 2
    b = (x2[1] - x0[1]) / 2

    for i, j in ti.ndrange(4, 4):
        # Here is the problem:
        k[2 * i, 2 * j] = b / a * (1 + 1 / 3 * l_y[i] * l_y[j]) * l_x[i] * l_x[j] + a / b * (1 - nu) / 2 * (1 + l_x[i] * l_x[j] / 3) * l_y[i] * l_y[j]
    return k

@ti.kernel
def init():
    for i, j in ele:
        ele[i, j][0] = j + i * n_no_x
        ele[i, j][1] = ele[i, j][0] + 1
        ele[i, j][2] = ele[i, j][1] + n_no_x
        ele[i, j][3] = ele[i, j][2] - 1

    for i, j in ti.ndrange(n_no_y, n_no_x):
        init_pos[2 * (j + i * n_no_x)] = j * (l / (n_no_x - 1))
        init_pos[2 * (j + i * n_no_x) + 1] = i * (l / (n_no_x - 1))

    for i, j in ele:
        x0 = ti.Vector([init_pos[2 * ele[i, j][0]], init_pos[2 * ele[i, j][0] + 1]])
        x1 = ti.Vector([init_pos[2 * ele[i, j][1]], init_pos[2 * ele[i, j][1] + 1]])
        x2 = ti.Vector([init_pos[2 * ele[i, j][2]], init_pos[2 * ele[i, j][2] + 1]])
        x3 = ti.Vector([init_pos[2 * ele[i, j][3]], init_pos[2 * ele[i, j][3] + 1]])

        k = k_ele(x0, x1, x2, x3)

init()

是不是由于矩阵的unrolling mechanisms?如果是的话,在这种每个循环都要新的矩阵的情况下是不是只能建立一个大的矩阵张量?

好像确实是unrolling的问题。把kl_xl_y改成张量能避免这个问题。但这样是不是储存占用就多了?
附改过的代码:



import taichi as ti
import numpy as np

ti.init(arch = ti.gpu)

# material parameters
nu = 0.3 #Poisson's ratio
l = 8.0 #length

# simulation parameters
n_no_x = 3 #no. of nodes in x direction
n_no_y = 2 #no. of nodes in y direction
n_no = n_no_x * n_no_y
n_no_active = (n_no_x - 1) * n_no_y #excluding Dirichlet nodes

ele = ti.Vector(4, dt = ti.i32, shape = (n_no_y - 1, n_no_x - 1)) #connectivity matrix
init_pos = ti.var(dt = ti.f32, shape = n_no * 2) # store initial node position (not updated for infinitesimal deformation)
ks = ti.var(dt = ti.f32, shape = (n_no_y - 1, n_no_x - 1, 8, 8))

l_x = ti.var(dt = ti.f32, shape = 4)
l_y = ti.var(dt = ti.f32, shape = 4)
l_x.from_numpy(np.array([-1, 1, 1, -1]))
l_y.from_numpy(np.array([-1, -1, 1, 1]))

@ti.func
def k_ele(x0, x1, x2, x3, eleI, eleJ):

    a = (x1[0] - x0[0]) / 2
    b = (x2[1] - x0[1]) / 2

    for i, j in ti.ndrange(4, 4):
        ks[eleI, eleJ, 2 * i, 2 * j] = b / a * (1 + 1 / 3 * l_y[i] * l_y[j]) * l_x[i] * l_x[j] + a / b * (1 - nu) / 2 * (1 + l_x[i] * l_x[j] / 3) * l_y[i] * l_y[j]

@ti.kernel
def init():
    for i, j in ele:
        ele[i, j][0] = j + i * n_no_x
        ele[i, j][1] = ele[i, j][0] + 1
        ele[i, j][2] = ele[i, j][1] + n_no_x
        ele[i, j][3] = ele[i, j][2] - 1

    for i, j in ti.ndrange(n_no_y, n_no_x):
        init_pos[2 * (j + i * n_no_x)] = j * (l / (n_no_x - 1))
        init_pos[2 * (j + i * n_no_x) + 1] = i * (l / (n_no_x - 1))

    for i, j in ele:
        x0 = ti.Vector([init_pos[2 * ele[i, j][0]], init_pos[2 * ele[i, j][0] + 1]])
        x1 = ti.Vector([init_pos[2 * ele[i, j][1]], init_pos[2 * ele[i, j][1] + 1]])
        x2 = ti.Vector([init_pos[2 * ele[i, j][2]], init_pos[2 * ele[i, j][2] + 1]])
        x3 = ti.Vector([init_pos[2 * ele[i, j][3]], init_pos[2 * ele[i, j][3] + 1]])

        k_ele(x0, x1, x2, x3, i, j)

init()

可能编译器还不够智能吧,手工循环展开就不报错了:
for i, j in ti.static(ti.ndrange(4, 4)):

然后会出一堆 warning 提示精度丢失,k 是故意用整数的吗?

谢谢,k应该是用浮点数。确实加了ti.static()就不报错了。刚刚发现这个document里也提到了(https://taichi.readthedocs.io/en/stable/meta.html)。

Btw, you can use ti.Matrix.zero(8, 8) to generate a 8x8 matrix filled with 0.
Or

m = ti.Matrix.empty(8, 8)
m.fill(0)

also works.

1 个赞

Thanks a lot! However, when I tried
k = ti.Matrix.zero(8, 8),
I got the following error:

[Taichi] mode=release
[Taichi] version 0.6.7, supported archs: [cpu, cuda, opengl], commit ca4d9dda, python 3.7.3
Traceback (most recent call last):
  File "cantilever.py", line 113, in <module>
    init()
  File "C:\Users\chenj\Anaconda3\lib\site-packages\taichi\lang\kernel.py", line 533, in wrapped
    return primal(*args, **kwargs)
  File "C:\Users\chenj\Anaconda3\lib\site-packages\taichi\lang\kernel.py", line 463, in __call__
    self.materialize(key=key, args=args, arg_features=arg_features)
  File "C:\Users\chenj\Anaconda3\lib\site-packages\taichi\lang\kernel.py", line 343, in materialize
    taichi_kernel = taichi_kernel.define(taichi_ast_generator)
  File "C:\Users\chenj\Anaconda3\lib\site-packages\taichi\lang\kernel.py", line 340, in taichi_ast_generator
    compiled()
  File "cantilever.py", line 94, in init
    k = k_ele(x0, x1, x2, x3)
  File "C:\Users\chenj\Anaconda3\lib\site-packages\taichi\lang\kernel.py", line 55, in __call__
    ret = self.compiled(*args)
  File "cantilever.py", line 56, in k_ele
    k = ti.Matrix.zero(8, 8)
  File "C:\Users\chenj\Anaconda3\lib\site-packages\taichi\lang\matrix.py", line 540, in zero
    for _ in range(n)])
  File "C:\Users\chenj\Anaconda3\lib\site-packages\taichi\lang\matrix.py", line 540, in <listcomp>
    for _ in range(n)])
  File "C:\Users\chenj\Anaconda3\lib\site-packages\taichi\lang\matrix.py", line 539, in <listcomp>
    return ti.Matrix([[ti.cast(0, dt) for _ in range(m)]
  File "C:\Users\chenj\Anaconda3\lib\site-packages\taichi\lang\ops.py", line 94, in cast
    return Expr(taichi_lang_core.value_cast(Expr(obj).ptr, type))
TypeError: value_cast(): incompatible function arguments. The following argument types are supported:
    1. (arg0: taichi_core.Expr, arg1: taichi::lang::DataType) -> taichi_core.Expr

Invoked with: <taichi_core.Expr object at 0x0000025A5BEC4A78>, 8

And with

m = ti.Matrix.empty(8, 8)
m.fill(0)

I got

AttributeError: type object 'Matrix' has no attribute 'empty'

error. Is this a problem of my version? Thanks!

For the first one, I forgot to specify the data type. The following one works: k = ti.Matrix.zero(ti.f32, 8, 8).

For the second one, my taichi\lang\matrix.py file doesn’t contain a method called empty. Maybe it’s not in my version?

1 个赞