taichi-dev / taichi_three

A soft renderer based on Taichi (work in progress)
https://t3.142857.red/
MIT License
223 stars 24 forks source link

About dimension independent programming #29

Closed Jack12xl closed 4 years ago

Jack12xl commented 4 years ago

About dimension independent programming:

Sry this issue is more like a search-for-help.

Basically, I am gonna extend a 2d simulation to 3d(or more specifically, this repo).

Although here mpm3d already shows a good example on both supporting 2d and 3d, I still wonder is there any more elegant way to do this in my setting?

For example, to calculate divergence in 2d setting, we could say:

 @ti.kernel
    def calDivergence(self, vf: ti.template(), vd: ti.template()):
        # vf : Data wrapper class for velocity field 
        # vf as ti.Vector.field(2, dtype=ti.f32, shape=[512, 512])
        # vd : Data wrapper class for velocity divergence
        # vd as ti.field(dtype=ti.f32, shape=[512, 512])
        for I in ti.grouped(vf.field):
            vl = vf.sample(I + ts.D.zy).x
            vr = vf.sample(I + ts.D.xy).x
            vb = vf.sample(I + ts.D.yz).y
            vt = vf.sample(I + ts.D.yx).y
            vc = vf.sample(I)
            # omit the boundary condition
            vd[I] = (vr - vl + vt - vb) * 0.5

For clarification( in case it matters ):

calDivergence is defined in here

vf class is defined here

To 3D

Here I want to extend this calDivergence to 3D: vf and vd would become 3d,

which means :

vf would more or less become ti.Vector.field(3, dtype=ti.f32, shape=[512, 512, 512])

and

vd : ti.field(dtype=ti.f32, shape=[512, 512, 512])

So our calDivergence would become something like


    @ti.kernel
    def calDivergence(self, vf: ti.template(), vd: ti.template()):
        if ( dimension2 ):
            for I in ti.grouped(vf.field):
                vl = vf.sample(I + ts.D.zy).x
                vr = vf.sample(I + ts.D.xy).x
                vb = vf.sample(I + ts.D.yz).y
                vt = vf.sample(I + ts.D.yx).y
                vc = vf.sample(I)
                # omit boundary condition 
                vd[I] = (vr - vl + vt - vb) * 0.5
        elif ( dimension3 ):
            for I in ti.grouped(vf.field):
                vl = vf.sample(I + ts.D.zyy).x
                vr = vf.sample(I + ts.D.xyy).x
                vb = vf.sample(I + ts.D.yzy).y
                vt = vf.sample(I + ts.D.yxy).y
                vh = vf.sample(I + ts.D.yyz).z
                vq = vf.sample(I + ts.D.yyx).z
                vc = vf.sample(I)
                # omit boundary condition
                vd[I] = (vr - vl + vt - vb + vq - vh) * 0.5

But in this way, the function would become somewhat clunky, hard to maintain and extend.

I mean, ti.grouped is already make it kind of dimension-independent. So I wonder is there any trick(magic function) to make it more dimension-independent ?

For example:

@ti.kernel
    def calDivergence(self, vf: ti.template(), vd: ti.template()):
        for I in ti.grouped(vf.field):
            tmp = magic_function(vf, vd, dim)
            # tmp = [vl, vr, vb, vt] in dimension 2
            # tmp = [vl, vr, vb, vt, vh, vq] in dimension 3

            vd[I] = sum(tmp)
archibate commented 4 years ago

import taichi as ti

@ti.kernel def calDivergence(self, vf: ti.template(), vd: ti.template()):    for I in ti.grouped(vf.field):        ret = 0.0        for i in ti.static(range(dim)):            D = ti.Vector.unit(dim, i)            res += vf.sample(I + D)[i]            ret -= vf.sample(I - D)[i]        vd[I] = ret * 0.5

@ti.func def magic_function(vf, vd):    ret = ti.static([])    for i in ti.static(range(dim)):        D = ti.Vector.unit(dim, i)        ret.append(vf.sample(I + D)[i])        ret.append(vf.sample(I - D)[i])    return ret  

双笙子佯谬 1931127624@qq.com

上海拆桥学院 桥梁爆破小组首席执行官

 

------------------ 原始邮件 ------------------ 发件人: "notifications"<notifications@github.com>; 发送时间: 2020年11月10日(星期二) 晚上6:12 收件人: "taichi-dev/taichi_three"<taichi_three@noreply.github.com>; 抄送: "Subscribed"<subscribed@noreply.github.com>; 主题: [taichi-dev/taichi_three] About dimension independent programming (#29)

Sry this issue is more like a search-for-help.

Basically, I am gonna extend a 2d simulation to 3d(or more specifically, this repo).

Although here mpm3d already shows a good example on both supporting 2d and 3d, I still wonder is there any more elegant way to do this in my setting?

For example, to calculate divergence in 2d setting, we could say: @ti.kernel def calDivergence(self, vf: ti.template(), vd: ti.template()): # vf : Data wrapper class for velocity field # vf as ti.Vector.field(2, dtype=ti.f32, shape=[512, 512]) # vd : Data wrapper class for velocity divergence # vd as ti.field(dtype=ti.f32, shape=[512, 512]) for I in ti.grouped(vf.field): vl = vf.sample(I + ts.D.zy).x vr = vf.sample(I + ts.D.xy).x vb = vf.sample(I + ts.D.yz).y vt = vf.sample(I + ts.D.yx).y vc = vf.sample(I) # omit the boundary condition vd[I] = (vr - vl + vt - vb) * 0.5

For clarification( in case it matters ):

calDivergence is defined in here

vf class is defined here

To 3D

Here I want to extend this calDivergence to 3D: vf and vd would become 3d,

which means :

vf would more or less become ti.Vector.field(3, dtype=ti.f32, shape=[512, 512, 512])

and

vd : ti.field(dtype=ti.f32, shape=[512, 512, 512])

So our calDivergence would become something like @ti.kernel def calDivergence(self, vf: ti.template(), vd: ti.template()): if ( dimension2 ): for I in ti.grouped(vf.field): vl = vf.sample(I + ts.D.zy).x vr = vf.sample(I + ts.D.xy).x vb = vf.sample(I + ts.D.yz).y vt = vf.sample(I + ts.D.yx).y vc = vf.sample(I) # omit boundary condition vd[I] = (vr - vl + vt - vb) 0.5 elif ( dimension3 ): for I in ti.grouped(vf.field): vl = vf.sample(I + ts.D.zyy).x vr = vf.sample(I + ts.D.xyy).x vb = vf.sample(I + ts.D.yzy).y vt = vf.sample(I + ts.D.yxy).y vh = vf.sample(I + ts.D.yyz).z vq = vf.sample(I + ts.D.yyx).z vc = vf.sample(I) # omit boundary condition vd[I] = (vr - vl + vt - vb + vq - vh) 0.5

I mean, ti.grouped is already make it kind of dimension-independent. So I wonder is there any trick to make it more dimension-independent ?

For example: @ti.kernel def t_div(self, vf: ti.template(), vd: ti.template()): for I in ti.grouped(vf.field): tmp = magic_function(vf, vd, dim) # tmp = [vl, vr, vb, vt] in dimension 2 # tmp = [vl, vr, vb, vt, vh, vq] in dimension 3 vd[I] = sum(tmp)

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe.

Jack12xl commented 4 years ago

Oh yeah♂ That's good ♂

That ti.Vector.unit really does the trick. Thanks a lot !

I'm closing it now.