Jack12xl / a-toy-fluid-engine

try to reimplement Euler based fluid
MIT License
46 stars 3 forks source link

Question about updating temporary global variable #3

Closed Jack12xl closed 4 years ago

Jack12xl commented 4 years ago

Title: Question about updating temporary global variable

Env

in case

[Taichi] mode=release

[Taichi] version 0.6.37, llvm 10.0.0, commit e0ac1d86, osx, python 3.8.3

[Taichi] Starting on arch=x64

In short

I want to access temporary variable(say init by ti.Vector() ) in taichi scope. However, the results turns out that in taichi scope , program could only capture the initial value of the temporary variable if the variable is not the input of this taichi scope function, but in py scope it could.

To be clear, here we have this script:

import taichi as ti
import math

ti.init(ti.cpu, debug=True)

@ti.data_oriented
class trsfrm:
    def __init__(self, translation=ti.Vector([0.0, 0.0]), orientation=0.0, localscale=1.0):
        '''
        class variable init by ti.Vector
        :param translation:
        :param orientation:
        :param localscale:
        '''
        self.translation = translation
        self.orientation = orientation % (2 * math.pi)
        self.localScale = localscale

    def __repr__(self):
        return '{} ( Trsln : {}, Ornttn: {}, lclScl: {})'.format(
            self.__class__.__name__,
            self.translation,
            self.orientation,
            self.localScale)

@ti.data_oriented
class trsfrm_field:
    def __init__(self):
        '''
        class member init by ti.Vector.field
        '''
        self.translation = ti.Vector.field(2, dtype=ti.f32, shape=[1])

        # self.orientation = orientation % (2 * math.pi)
        # self.localScale = localscale

    def __repr__(self):
        return '{} ( Trsln : {})'.format(
            self.__class__.__name__,
            self.translation,
            )

@ti.kernel
def kern_test_with_input(t_1 : ti.template(), t_2 : ti.template()):
    print("kern with input t1: ", t_1)
    print("kern with input t2: ", t_2[0])

@ti.kernel
def kern_test_without_input():
    print("kern without input t1: ", t1.translation)
    print("kern without input t2: ", t2.translation[0])

@ti.kernel
def kern_add(t:ti.template()):
    t[0] += ti.Vector([2.0, 2.0])
    # print("kern add field", t[0])

t1 = trsfrm()
t2 = trsfrm_field()

while (True):

    t1.translation = t1.translation + ti.Vector([2.0, 2.0])
    print(t1)
    print("py scope print t1: ",t1.translation)

    # increment t2
    kern_add(t2.translation)

    kern_test_without_input()
    # can not capture the incremented t1
    kern_test_with_input(t1.translation, t2.translation)
    print(" ")

What's the program?

Bascially, the program has two forms of class trsfm, one(trsfm) init with ti.Vector, another(trsfrm_field) with ti.Vector.field().

My current implementation is class trsfrm, what I wanna do is to increment the translation member of class trsfrm and capture the incremented class trsfrm in taichi scope.

However, in kern_test_without_input it could only capture the initial value( keep printing [2.0, 2.0] instead of incrementing itself ). The funny thing to me is that: in py scope the t1 still updates itself . While in kern_test_input, with t1 as input it can capture the increasing value.

The truth is, the trsfrm_field no matter without or with input, the taichi scope could always capture the increasement.

The program output is :

trsfrm ( Trsln : [2. 2.], Ornttn: 0.0, lclScl: 1.0)
py scope print t1:  [2. 2.]
[Taichi] materializing...
kern without input t1:  [2.000000, 2.000000]
kern without input t2:  [2.000000, 2.000000]
kern with input t1:  [2.000000, 2.000000]
kern with input t2:  [2.000000, 2.000000]

trsfrm ( Trsln : [4. 4.], Ornttn: 0.0, lclScl: 1.0)
py scope print t1:  [4. 4.]
kern without input t1:  [2.000000, 2.000000]
kern without input t2:  [4.000000, 4.000000]
kern with input t1:  [4.000000, 4.000000]
kern with input t2:  [4.000000, 4.000000]

trsfrm ( Trsln : [6. 6.], Ornttn: 0.0, lclScl: 1.0)
py scope print t1:  [6. 6.]
kern without input t1:  [2.000000, 2.000000]
kern without input t2:  [6.000000, 6.000000]
kern with input t1:  [6.000000, 6.000000]
kern with input t2:  [6.000000, 6.000000]

The kern without input t1 is always the same. Due to some reasons I expect it to increase as well.

Sry about the wording

So The Question:

Is there an elegant way to capture the ti.Vector change in taichi global scope?

Why do I ask this?

I want to implement a transform class for collider in euler based fluid simulation in order to make the collider rotate or translate. [Here]() is the repo link.

The circle(collider) stands still if I do not make the transform.rotation as the function input in rendering function. (currently I access the )

Currently my walkaround is either

But personally, I am not a big fan of capturing the increasement by adding t1 as input because in that way it may take undefined multiple number of colliders as input. And probably due to this, although the ball can rotate, the fps drops drastically(from 15fps -> 8fps). From the experience, it should not happen since the function did not change that much whether with or without the input.

Also init the transform member with ti.field is not that feasible to me because ti.field cannot be init after materialize or start an kernel function. In this way we somehow cannot trivially add new collider with transform as member to the scene.

So is there any walkaround for this ? 0.0

Hope my statement is clear and clean...

Jack12xl commented 4 years ago

Has been discussed in Taichi forum. Would make the transform variable become ti.field