背景
想写一个简化的粒子法程序,用 GUI
渲染。
问题
在生成粒子位置信息后,使用 palette
渲染两种不同的粒子时出现了颜色错误的情况,如下图所示,而且改变粒子大小后依然是左下角的这四个粒子颜色错误。另外,这四个粒子的颜色还会不定地变化一下,不过待一会儿之后还是变成正确的颜色。
使用 1.2.2
版本和 1.4.1
版本的CPU
或CUDA
都会这样。虽然不影响使用但感觉很奇怪,说不定是个bug?
简单代码如下:
import taichi as ti
import numpy as np
from functools import reduce
ti.init(arch=ti.cuda)
# Simulation parameters
dim = 2
dx = 0.1
# Simulation geometries
domain_size = np.array([6.0, 4.0])
cube_size, cube_translation = [2.0, 1.0], [0.5, 0.5]
dummy_layer = 3
dummy_b_size, dummy_b_translation = [domain_size[0] - 1.0 + 2*dummy_layer*dx, dummy_layer*dx], [0.5 - dummy_layer*dx, 0.5 - dummy_layer*dx]
# GUI parameters
screen_to_world_ratio = 150
res = np.array(domain_size * (screen_to_world_ratio * 1.05), dtype=np.int32)
bg_colour = 0x112f41
colour_water = 0x068587
colour_dummy = 0x8e8e8e
colour_palette = [colour_water, colour_dummy]
@ti.dataclass
class Particle:
x: ti.types.vector(2, float)
type: int # 1: water, -1: dummy
colour_indices: int
def calc_cube_particle_num(size, translation, dim=2, offset=None):
num_dim = []
range_offset = offset if offset is not None else 0.1
for i in range(dim):
off = range_offset if size[i] >= 0 else -range_offset
num_dim.append(np.arange(translation[i] + off / 2.0, translation[i] + size[i] + 1e-5, off))
return reduce(lambda x, y: x * y, [len(n) for n in num_dim]), num_dim
# Geometries
pt_num = ti.field(int, shape=())
pt_num_water, num_dim_water = calc_cube_particle_num(size=cube_size, translation=cube_translation, dim=dim, offset=dx)
pt_num_dummy_b, num_dim_dummy_b = calc_cube_particle_num(size=dummy_b_size, translation=dummy_b_translation, dim=dim, offset=dx)
pt_num[None] = pt_num_water + pt_num_dummy_b
new_pos_water = np.array(np.meshgrid(*num_dim_water, sparse=False, indexing='ij'), dtype=np.float32).reshape(-1, pt_num_water).transpose()
new_pos_dummy_b = np.array(np.meshgrid(*num_dim_dummy_b, sparse=False, indexing='ij'), dtype=np.float32).reshape(-1, pt_num_dummy_b).transpose()
new_pos = np.concatenate((new_pos_water, new_pos_dummy_b), axis=0)
pt = Particle.field(shape=pt_num[None])
pt.x.from_numpy(new_pos)
@ti.kernel
def init_pts():
for i in range(pt_num[None]):
if i < pt_num_water:
pt[i].type = 1
pt[i].colour_indices = 0
else:
pt[i].type = -1
pt[i].colour_indices = 1
def render(gui):
gui.clear(bg_colour)
pos_np = pt.x.to_numpy()
for j in range(dim):
pos_np[:, j] *= screen_to_world_ratio / res[j]
gui.circles(pos_np, radius=dx/2*screen_to_world_ratio, palette = colour_palette, palette_indices=pt.colour_indices)
gui.show()
def main():
init_pts()
print(f"dx = {dx}, total pts {pt_num[None]}, water pts {pt_num_water}, dummy pts {pt_num[None] - pt_num_water}")
gui = ti.GUI("test", res)
while gui.running and not gui.get_event(gui.ESCAPE):
render(gui)
if __name__ == '__main__':
main()