Exemple #1
0
class MPM3:
    def __init__(self, **kwargs):
        self.c = tc_core.create_simulation3d('mpm')
        self.c.initialize(P(**kwargs))
        self.directory = tc.get_output_path(get_unique_task_id())
        self.video_manager = VideoManager(self.directory, 960, 540)
        try:
            os.mkdir(self.directory)
        except Exception as e:
            print e
        self.particle_renderer = ParticleRenderer('shadow_map',
                                                  shadow_map_resolution=0.5,
                                                  alpha=0.5,
                                                  shadowing=0.1,
                                                  ambient_light=0.2,
                                                  light_direction=(-1, 1, -1))
        self.resolution = kwargs['resolution']
        self.frame = 0

    def step(self, step_t):
        t = self.c.get_current_time()
        print 'Simulation time:', t
        T = time.time()
        self.c.step(step_t)
        print 'Time:', time.time() - T
        image_buffer = tc_core.RGBImageFloat(self.video_manager.width,
                                             self.video_manager.height,
                                             Vector(0, 0, 0.0))
        particles = self.c.get_render_particles()
        particles.write(self.directory + '/particles%05d.bin' % self.frame)
        res = map(float, self.resolution)
        radius = res[0] * 2.5
        theta = 0
        camera = Camera('pinhole',
                        origin=(0, res[1], res[2] * 5),
                        look_at=(0, 0, 0),
                        up=(0, 1, 0),
                        fov=70,
                        width=10,
                        height=10)
        self.particle_renderer.set_camera(camera)
        self.particle_renderer.render(image_buffer, particles)
        img = image_buffer_to_ndarray(image_buffer)
        img = LDRDisplay(exposure=0.1).process(img)
        cv2.imshow('Vis', img)
        cv2.waitKey(1)
        self.video_manager.write_frame(img)
        self.frame += 1

    def make_video(self):
        self.video_manager.make_video()
Exemple #2
0
class NBody:
    def __init__(self, **kwargs):
        self.c = tc_core.create_simulation3('nbody')
        self.c.initialize(P(**kwargs))
        self.directory = taichi.get_output_path(get_unique_task_id())
        try:
            os.mkdir(self.directory)
        except Exception as e:
            print(e)
        self.video_manager = VideoManager(self.directory, 512, 512)
        self.particle_renderer = ParticleRenderer('shadow_map',
                                                  shadow_map_resolution=0.01,
                                                  alpha=0.12,
                                                  shadowing=0.1,
                                                  ambient_light=0.3,
                                                  light_direction=(1, 3, -3))
        self.step_counter = 0

    def get_output_path(self, path):
        return '/'.join([self.directory, path])

    def step(self, step_t):
        t = self.c.get_current_time()
        print('Simulation time:', t)
        T = time.time()
        self.c.step(step_t)
        print('Time:', time.time() - T)
        image_buffer = tc_core.Array2DVector3(self.video_manager.width,
                                              self.video_manager.height,
                                              Vector(0, 0, 0.0))
        particles = self.c.get_render_particles()
        particles.write(
            self.get_output_path('particles%05d.bin' % self.step_counter))
        camera = Camera('pinhole',
                        origin=(0, 0, 50),
                        look_at=(0, 0, 0),
                        up=(0, 1, 0),
                        fov=70,
                        width=self.video_manager.width,
                        height=self.video_manager.height)
        self.particle_renderer.set_camera(camera)
        self.particle_renderer.render(image_buffer, particles)
        img = image_buffer_to_ndarray(image_buffer)
        # img = LDRDisplay(exposure=1, adaptive_exposure=False).process(img)
        show_image('Vis', img)
        self.video_manager.write_frame(img)
        self.step_counter += 1

    def make_video(self):
        self.video_manager.make_video()
class ParticleViewer:
    def __init__(self, directory, width, height):
        self.directory = '../output/frames/' + get_unique_task_id() + '/'
        self.input_directory = '../output/frames/' + directory + '/'
        self.video_manager = VideoManager(self.directory, width, height)
        self.particle_renderer = ParticleRenderer('shadow_map',
                                                  shadow_map_resolution=0.5,
                                                  alpha=0.5,
                                                  shadowing=0.1,
                                                  ambient_light=0.2,
                                                  light_direction=(-1, 1, -1))
        try:
            os.mkdir(self.directory)
        except Exception as e:
            print e
        self.step_counter = 0

    def view(self, frame, camera):
        particles = tc_core.RenderParticles()
        ret = particles.read(self.input_directory +
                             'particles%05d.bin' % frame)
        if not ret:
            print 'read file failed'
            return False
        image_buffer = tc_core.RGBImageFloat(self.video_manager.width,
                                             self.video_manager.height,
                                             Vector(0, 0, 0.0))
        self.particle_renderer.set_camera(camera)
        self.particle_renderer.render(image_buffer, particles)
        img = image_buffer_to_ndarray(image_buffer)
        #img = LDRDisplay(exposure=1, adaptive_exposure=False).process(img)
        cv2.imshow('Vis', img)
        cv2.waitKey(1)
        self.video_manager.write_frame(img)
        return True

    def make_video(self):
        self.video_manager.make_video()
Exemple #4
0
class MPM3:
    def __init__(self, **kwargs):
        self.c = tc_core.create_simulation3d('mpm')
        self.c.initialize(P(**kwargs))
        self.task_id = get_unique_task_id()
        self.directory = tc.get_output_path(self.task_id)
        try:
            os.mkdir(self.directory)
        except Exception as e:
            print e
        self.video_manager = VideoManager(self.directory, 540, 540)
        self.particle_renderer = ParticleRenderer('shadow_map',
                                                  shadow_map_resolution=0.3,
                                                  alpha=0.7,
                                                  shadowing=2,
                                                  ambient_light=0.01,
                                                  light_direction=(1, 1, 0))
        self.resolution = kwargs['resolution']
        self.frame = 0

        dummy_levelset = self.create_levelset()

        def dummy_levelset_generator(_):
            return dummy_levelset

        self.levelset_generator = dummy_levelset_generator

    def add_particles(self, **kwargs):
        self.c.add_particles(P(**kwargs))

    def update_levelset(self, t0, t1):
        levelset = tc.core.DynamicLevelSet3D()
        levelset.initialize(t0, t1,
                            self.levelset_generator(t0).levelset,
                            self.levelset_generator(t1).levelset)
        self.c.set_levelset(levelset)

    def set_levelset(self, levelset, is_dynamic_levelset=False):
        if is_dynamic_levelset:
            self.levelset_generator = levelset
        else:

            def levelset_generator(_):
                return levelset

            self.levelset_generator = levelset_generator

    def get_current_time(self):
        return self.c.get_current_time()

    def step(self, step_t):
        t = self.c.get_current_time()
        print 'Simulation time:', t
        T = time.time()
        self.update_levelset(t, t + step_t)
        print 'Update Leveset Time:', time.time() - T
        T = time.time()
        self.c.step(step_t)
        print 'Step Time:', time.time() - T
        image_buffer = tc_core.Array2DVector3(self.video_manager.width,
                                              self.video_manager.height,
                                              Vector(0, 0, 0.0))
        particles = self.c.get_render_particles()
        particles.write(self.directory + '/particles%05d.bin' % self.frame)
        res = map(float, self.resolution)
        camera = Camera('pinhole',
                        origin=(0, res[1] * 0.4, res[2] * 1.4),
                        look_at=(0, -res[1] * 0.5, 0),
                        up=(0, 1, 0),
                        fov=90,
                        width=10,
                        height=10)
        self.particle_renderer.set_camera(camera)
        self.particle_renderer.render(image_buffer, particles)
        img = image_buffer_to_ndarray(image_buffer)
        img = LDRDisplay(exposure=2.0, adaptive_exposure=False).process(img)
        show_image('Vis', img)
        self.video_manager.write_frame(img)
        self.frame += 1

    def get_directory(self):
        return self.directory

    def make_video(self):
        self.video_manager.make_video()

    def create_levelset(self):
        return LevelSet3D(self.resolution, Vector(0.0, 0.0, 0.0))

    def test(self):
        return self.c.test()
Exemple #5
0
class SimulationWindow(pyglet.window.Window):
    def __init__(self,
                 max_side,
                 simulator,
                 color_scheme,
                 levelset_supersampling=2,
                 show_grid=False,
                 show_images=True,
                 rescale=True,
                 video_framerate=24,
                 video_output=True,
                 substep=False,
                 need_press=False):
        if rescale:
            scale = min(1.0 * max_side / simulator.res[0],
                        1.0 * max_side / simulator.res[1])
            width = int(round(scale * simulator.res[0]))
            height = int(round(scale * simulator.res[1]))
        else:
            width = max_side
            height = max_side

        super(SimulationWindow,
              self).__init__(width=width,
                             height=height,
                             fullscreen=False,
                             caption='Taichi',
                             config=pyglet.gl.Config(sample_buffers=0,
                                                     samples=0,
                                                     depth_size=16,
                                                     double_buffer=True))
        self.width = width
        self.height = height
        self.video_framerate = video_framerate
        self.task_id = get_unique_task_id()
        self.simulator = simulator
        self.frame_count = 0
        self.color_scheme = color_scheme
        self.show_images = show_images
        self.levelset_supersampling = levelset_supersampling
        self.show_grid = show_grid
        self.quit_pressed = False
        self.output_directory = os.path.join(get_output_directory(),
                                             self.task_id)
        self.cpu_time = 0
        os.mkdir(self.output_directory)
        self.substep = substep
        self.video_output = video_output
        self.video_manager = VideoManager(self.output_directory,
                                          automatic_build=self.video_output)
        self.need_press = need_press
        self.pressed = False
        pyglet.clock.schedule_interval(self.update, 1 / 120.0)
        pyglet.app.run()

    def on_key_press(self, symbol, modifiers):
        if symbol == pyglet.window.key.J:
            self.pressed = True
        if symbol == pyglet.window.key.K:
            self.need_press = not self.need_press
        if symbol == pyglet.window.key.Q:
            exit(0)
        if symbol == pyglet.window.key.ESCAPE:
            self.quit_pressed = True

    def update(self, _):
        if not self.quit_pressed and not self.simulator.ended():
            if not self.need_press or self.pressed:
                t = time.time()
                if self.substep:
                    self.simulator.step(True)
                else:
                    self.simulator.step()
                ela_t = time.time() - t
                print 'Elapsed time:', ela_t
                self.cpu_time += ela_t
            self.pressed = False
        else:
            if self.video_output:
                self.video_manager.make_video()
            exit(0)
        self.redraw()
        self.save_frame()

    def save_frame(self):
        gl.glPixelTransferf(gl.GL_ALPHA_BIAS, 1.0)
        buffer = pyglet.image.get_buffer_manager().get_color_buffer()
        data = buffer.get_image_data().data
        img = (np.fromstring(data, dtype=np.uint8).reshape(
            (self.height, self.width, 4)) / 255.0).astype(np.float32).swapaxes(
                0, 1)
        self.video_manager.write_frame(img[:, :, :])
        gl.glPixelTransferf(gl.GL_ALPHA_BIAS, 0.0)
        self.frame_count += 1

    def redraw(self):
        glClearColor(*normalized_color_255(*self.color_scheme['background']))
        self.clear()
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnable(GL_BLEND)
        background = self.simulator.get_background_image(
            self.width, self.height)
        if background:
            background.blit(0, 0, 0, self.width, self.height)
        ls_width = self.width * self.levelset_supersampling
        ls_height = self.height * self.levelset_supersampling
        background_images, foreground_images = self.simulator.get_levelset_images(
            ls_width, ls_height, self.color_scheme)
        if self.show_images:
            for img in background_images:
                img.blit(0, 0, 0, self.width, self.height)
        if self.show_grid:
            self.render_grid()

        self.render_particles()

        if self.show_images:
            for img in foreground_images:
                img.blit(0, 0, 0, self.width, self.height)

        label = pyglet.text.Label('sim. t = %.5f' %
                                  (self.simulator.get_current_time()),
                                  font_name='Rockwell',
                                  font_size=12,
                                  x=10,
                                  y=20,
                                  anchor_x='left',
                                  anchor_y='top')
        label.color = self.color_scheme['label']
        label.draw()
        label = pyglet.text.Label('cpu = %.5f' % self.cpu_time,
                                  font_name='Rockwell',
                                  font_size=12,
                                  x=10,
                                  y=40,
                                  anchor_x='left',
                                  anchor_y='top')
        label.color = self.color_scheme['label']
        label.draw()
        label = pyglet.text.Label('cpu/frame = %.5f' %
                                  (self.cpu_time / (1 + self.frame_count)),
                                  font_name='Rockwell',
                                  font_size=12,
                                  x=10,
                                  y=60,
                                  anchor_x='left',
                                  anchor_y='top')
        label.color = self.color_scheme['label']
        label.draw()

    def render_grid(self):
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glTranslatef(0, 0, 0)
        glScalef(1.0 * self.width / self.simulator.config['res'][0],
                 1.0 * self.height / self.simulator.config['res'][1], 0)

        line_num_x = self.simulator.resolution[0]
        line_num_y = self.simulator.resolution[1]
        positions = []
        for i in range(1, line_num_x):
            positions.append(1.0 * i)
            positions.append(0.0)
            positions.append(1.0 * i)
            positions.append(line_num_y)
        for i in range(1, line_num_y):
            positions.append(0.0)
            positions.append(1.0 * i)
            positions.append(line_num_x)
            positions.append(1.0 * i)

        points = 2 * (line_num_x + line_num_y - 2)
        pyglet.graphics.draw(points, gl.GL_LINES, ('v2f', positions),
                             ('c4B', [128, 128, 128, 50] * points))
        glPopMatrix()

    def render_particles(self):
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glTranslatef(0, 0, 0)
        glScalef(1.0 * self.width / self.simulator.config['res'][0],
                 1.0 * self.height / self.simulator.config['res'][1], 0)

        particles = self.simulator.get_particles()

        positions = []
        colors = []
        glPointSize(1.0)
        for p in particles:
            positions.append(p.position.x)
            positions.append(p.position.y)
            if p.color.x != -1:
                color = p.color * 255
                color = tuple(map(int, (color.x, color.y, color.z, 200)))
            else:
                color = self.color_scheme['particles']
            for i in range(4):
                colors.append(color[i])
        pyglet.graphics.draw(len(particles), gl.GL_POINTS, ('v2f', positions),
                             ('c4B', colors))
        glPopMatrix()
Exemple #6
0
class MPM:
    def __init__(self, snapshot_interval=20, **kwargs):
        res = kwargs['res']
        self.frame_dt = kwargs.get('frame_dt', 0.01)
        if 'frame_dt' not in kwargs:
            kwargs['frame_dt'] = self.frame_dt
        self.num_frames = kwargs.get('num_frames', 1000)
        if len(res) == 2:
            self.c = tc_core.create_simulation2('mpm')
            self.Vector = tc_core.Vector2f
            self.Vectori = tc_core.Vector2i
        else:
            self.c = tc.core.create_simulation3('mpm')
            self.Vector = tc_core.Vector3f
            self.Vectori = tc_core.Vector3i

        self.snapshot_interval = snapshot_interval

        if 'task_id' in kwargs:
            self.task_id = kwargs['task_id']
        else:
            self.task_id = sys.argv[0].split('.')[0]
        if 'delta_x' not in kwargs:
            kwargs['delta_x'] = 1.0 / res[0]

        print('delta_x = {}'.format(kwargs['delta_x']))
        print('task_id = {}'.format(self.task_id))

        self.directory = tc.get_output_path('mpm/' + self.task_id, True)
        self.snapshot_directory = os.path.join(self.directory, 'snapshots')
        self.video_manager = VideoManager(self.directory)
        kwargs['frame_directory'] = self.video_manager.get_frame_directory()

        try:
            opts, args = getopt.getopt(sys.argv[1:], 'c:d:',
                                       ['continue=', 'dt-multiplier='])
        except getopt.GetoptError as err:
            print(err)
            # TODO: output usage here
            sys.exit()
        self.continue_opt = False
        self.continue_frame = ''
        for o, a in opts:
            if o in ('--continue', '-c'):
                print('clear_output_directory is disabled with --continue.')
                self.continue_opt = True
                self.continue_frame = int(a)
            elif o in ('--dt-multiplier', '-d'):
                kwargs['dt-multiplier'] = float(a)

        self.c.initialize(P(**kwargs))
        self.check_directory(self.directory)
        self.check_directory(self.snapshot_directory)
        vis_res = self.c.get_vis_resolution()
        self.video_manager.width = vis_res.x
        self.video_manager.height = vis_res.y
        self.particle_renderer = ParticleRenderer('shadow_map',
                                                  shadow_map_resolution=0.3,
                                                  alpha=0.7,
                                                  shadowing=2,
                                                  ambient_light=0.01,
                                                  light_direction=(1, 1, 0))
        self.res = kwargs['res']
        self.c.frame = 0

        dummy_levelset = self.create_levelset()

        def dummy_levelset_generator(_):
            return dummy_levelset

        self.levelset_generator = dummy_levelset_generator
        self.start_simulation_time = None
        self.simulation_total_time = None
        self.visualize_count = 0
        self.visualize_count_limit = 400000.0

    def check_directory(self, directory):
        try:
            os.mkdir(directory)
        except OSError as exc:
            if exc.errno != errno.EEXIST:
                raise

    def add_particles(self, **kwargs):
        if 'scripted_rotation' in kwargs:
            kwargs['scripted_rotation_id'] = function_addresses.index(
                kwargs['scripted_rotation'])
        if 'scripted_position' in kwargs:
            kwargs['scripted_position_id'] = function_addresses.index(
                kwargs['scripted_position'])
        return self.c.add_particles(P(**kwargs))

    def update_levelset(self, t0, t1):
        if len(self.res) == 2:
            levelset = tc.core.DynamicLevelSet2D()
        else:
            levelset = tc.core.DynamicLevelSet3D()
        levelset.initialize(t0, t1,
                            self.levelset_generator(t0).levelset,
                            self.levelset_generator(t1).levelset)
        self.c.set_levelset(levelset)

    def set_levelset(self, levelset, is_dynamic_levelset=False):
        if is_dynamic_levelset:
            self.levelset_generator = levelset
        else:

            def levelset_generator(_):
                return levelset

            self.levelset_generator = levelset_generator

    def get_current_time(self):
        return self.c.get_current_time()

    def step(self, step_t, camera=None):
        t = self.c.get_current_time()
        print('* Current t: %.3f' % t)
        self.update_levelset(t, t + step_t)
        T = time.time()
        if not self.start_simulation_time:
            self.start_simulation_time = T
        if not self.simulation_total_time:
            self.simulation_total_time = 0
        self.c.step(step_t)
        self.simulation_total_time += time.time() - T
        print('* Step Time: %.2f [tot: %.2f per frame %.2f]' %
              (time.time() - T, time.time() - self.start_simulation_time,
               self.simulation_total_time / (self.c.frame + 1)))
        image_buffer = tc_core.Array2DVector3(
            Vectori(self.video_manager.width, self.video_manager.height),
            Vector(0, 0, 0.0))
        '''
    particles = self.c.get_render_particles()
    try:
      os.mkdir(self.directory + '/particles')
    except:
      pass
    particles.write(self.directory + '/particles/%05d.bin' % self.c.frame)
    '''
        res = list(map(float, self.res))
        r = res[0]
        if not camera:
            camera = Camera('pinhole',
                            origin=(0, r * 0.4, r * 1.4),
                            look_at=(0, -r * 0.5, 0),
                            up=(0, 1, 0),
                            fov=90,
                            res=(10, 10))
        if False:
            self.particle_renderer.set_camera(camera)
            self.particle_renderer.render(image_buffer, particles)
            img = image_buffer_to_ndarray(image_buffer)
            img = LDRDisplay(exposure=2.0,
                             adaptive_exposure=False).process(img)
            show_image('Vis', img)
            self.video_manager.write_frame(img)

    def get_directory(self):
        return self.directory

    def make_video(self):
        self.video_manager.make_video()

    def create_levelset(self):
        ls = LevelSet(Vectori(self.res), self.Vector(0.0))
        return ls

    def test(self):
        return self.c.test()

    def get_mpi_world_rank(self):
        return self.c.get_mpi_world_rank()

    def visualize(self):
        self.c.visualize()
        self.visualize_count += 1
        if self.visualize_count == int(self.visualize_count_limit):
            self.video_manager.make_video()
            self.visualize_count_limit *= math.sqrt(2)

    def get_debug_information(self):
        return self.c.get_debug_information()

    def clear_output_directory(self):
        frames_dir = os.path.join(self.directory, 'frames')
        taichi.clear_directory_with_suffix(frames_dir, 'bgeo')
        taichi.clear_directory_with_suffix(frames_dir, 'obj')
        # taichi.clear_directory_with_suffix(self.snapshot_directory, 'tcb')

    def simulate(self,
                 clear_output_directory=False,
                 frame_update=None,
                 update_frequency=1):
        # do restart
        if self.continue_opt:
            path = self.snapshot_directory
            files = [f for f in os.listdir(path) if f.endswith('.tcb')]
            files.sort()
            if not '{:04d}.tcb'.format(self.continue_frame) in files:
                print('Snapshot is not found.')
                print('The lastest one is ', files[-1], '.')
                sys.exit()
            f = self.get_snapshot_file_name(self.continue_frame)
            self.load(os.path.join(path, f))
        elif clear_output_directory:
            self.clear_output_directory()
        # do main cycle
        while self.c.frame < self.num_frames:
            print('Simulating frame {}'.format(self.c.frame + 1))
            for k in range(update_frequency):
                if frame_update:
                    frame_update(self.get_current_time(),
                                 self.frame_dt / update_frequency)
                self.step(self.frame_dt / update_frequency)
            self.visualize()
            self.c.frame += 1
            if self.c.frame % self.snapshot_interval == 0:
                self.save(self.get_snapshot_file_name(self.c.frame))

    def simulate_with_energy(self,
                             clear_output_directory=False,
                             print_profile_info=False,
                             frame_update=None,
                             update_frequency=1):
        # do restart
        if clear_output_directory:
            self.clear_output_directory()
        # do main cycle
        energy = []
        while self.c.frame < self.num_frames:
            print('Simulating frame {}'.format(self.c.frame + 1))
            for k in range(update_frequency):
                if frame_update:
                    frame_update(self.get_current_time(),
                                 self.frame_dt / update_frequency)
                self.step(self.frame_dt / update_frequency)
            self.visualize()
            self.c.frame += 1
            energy.append(float(
                self.general_action(action="calculate_energy")))
        return energy

    def general_action(self, **kwargs):
        return self.c.general_action(P(**kwargs))

    def add_articulation(self, **kwargs):
        kwargs['action'] = 'add_articulation'
        self.c.general_action(P(**kwargs))

    def delete_particles_inside_level_set(self):
        self.update_levelset(self.c.get_current_time(),
                             self.c.get_current_time() + 1)
        self.c.general_action(P(action='delete_particles_inside_level_set'))

    def action(self, **kwargs):
        self.c.general_action(P(**kwargs))

    def save(self, fn):
        self.action(action="save", file_name=fn)

    def load(self, fn):
        script_dict = {}
        for i, func in enumerate(function_addresses):
            script_dict['script{:05d}'.format(i)] = func
        print(script_dict)
        self.action(action="load", file_name=fn, **script_dict)

    def get_snapshot_file_name(self, iteration):
        return os.path.join(self.snapshot_directory,
                            '{:04d}.tcb'.format(iteration))
Exemple #7
0
class MPM:
    def __init__(self, **kwargs):
        res = kwargs['res']
        self.frame_dt = kwargs.get('frame_dt', 0.01)
        if 'frame_dt' not in kwargs:
            kwargs['frame_dt'] = self.frame_dt
        self.num_frames = kwargs.get('num_frames', 1000)
        if len(res) == 2:
            self.c = tc_core.create_simulation2('mpm')
            self.Vector = tc_core.Vector2f
            self.Vectori = tc_core.Vector2i
        else:
            self.c = tc.core.create_simulation3('mpm')
            self.Vector = tc_core.Vector3f
            self.Vectori = tc_core.Vector3i

        if 'task_id' in kwargs:
            self.task_id = kwargs['task_id']
        else:
            self.task_id = sys.argv[0].split('.')[0]
        if 'delta_x' not in kwargs:
            kwargs['delta_x'] = 1.0 / res[0]
        else:
            self.task_id = sys.argv[0].split('.')[0]

        print('delta_x = {}'.format(kwargs['delta_x']))
        print('task_id = {}'.format(self.task_id))

        self.directory = tc.get_output_path(self.task_id)
        self.video_manager = VideoManager(self.directory)
        kwargs['frame_directory'] = self.video_manager.get_frame_directory()
        self.c.initialize(P(**kwargs))
        try:
            os.mkdir(self.directory)
        except OSError as exc:
            if exc.errno != errno.EEXIST:
                raise
        vis_res = self.c.get_vis_resolution()
        self.video_manager.width = vis_res.x
        self.video_manager.height = vis_res.y
        self.particle_renderer = ParticleRenderer('shadow_map',
                                                  shadow_map_resolution=0.3,
                                                  alpha=0.7,
                                                  shadowing=2,
                                                  ambient_light=0.01,
                                                  light_direction=(1, 1, 0))
        self.res = kwargs['res']
        self.frame = 0

        dummy_levelset = self.create_levelset()

        def dummy_levelset_generator(_):
            return dummy_levelset

        self.levelset_generator = dummy_levelset_generator
        self.start_simulation_time = None
        self.simulation_total_time = None
        self.visualize_count = 0
        self.visualize_count_limit = 400000.0

    def add_particles(self, **kwargs):
        return self.c.add_particles(P(**kwargs))

    def update_levelset(self, t0, t1):
        if len(self.res) == 2:
            levelset = tc.core.DynamicLevelSet2D()
        else:
            levelset = tc.core.DynamicLevelSet3D()
        levelset.initialize(t0, t1,
                            self.levelset_generator(t0).levelset,
                            self.levelset_generator(t1).levelset)
        self.c.set_levelset(levelset)

    def set_levelset(self, levelset, is_dynamic_levelset=False):
        if is_dynamic_levelset:
            self.levelset_generator = levelset
        else:

            def levelset_generator(_):
                return levelset

            self.levelset_generator = levelset_generator

    def get_current_time(self):
        return self.c.get_current_time()

    def step(self, step_t, camera=None):
        t = self.c.get_current_time()
        print('* Current t: %.3f' % t)
        self.update_levelset(t, t + step_t)
        T = time.time()
        if not self.start_simulation_time:
            self.start_simulation_time = T
        if not self.simulation_total_time:
            self.simulation_total_time = 0
        self.c.step(step_t)
        self.simulation_total_time += time.time() - T
        print('* Step Time: %.2f [tot: %.2f per frame %.2f]' %
              (time.time() - T, time.time() - self.start_simulation_time,
               self.simulation_total_time / (self.frame + 1)))
        image_buffer = tc_core.Array2DVector3(
            Vectori(self.video_manager.width, self.video_manager.height),
            Vector(0, 0, 0.0))
        particles = self.c.get_render_particles()
        try:
            os.mkdir(self.directory + '/particles')
        except:
            pass
        particles.write(self.directory + '/particles/%05d.bin' % self.frame)
        res = list(map(float, self.res))
        r = res[0]
        if not camera:
            camera = Camera('pinhole',
                            origin=(0, r * 0.4, r * 1.4),
                            look_at=(0, -r * 0.5, 0),
                            up=(0, 1, 0),
                            fov=90,
                            res=(10, 10))
        if False:
            self.particle_renderer.set_camera(camera)
            self.particle_renderer.render(image_buffer, particles)
            img = image_buffer_to_ndarray(image_buffer)
            img = LDRDisplay(exposure=2.0,
                             adaptive_exposure=False).process(img)
            show_image('Vis', img)
            self.video_manager.write_frame(img)
        self.frame += 1

    def get_directory(self):
        return self.directory

    def make_video(self):
        self.video_manager.make_video()

    def create_levelset(self):
        ls = LevelSet(Vectori(self.res), self.Vector(0.0))
        return ls

    def test(self):
        return self.c.test()

    def get_mpi_world_rank(self):
        return self.c.get_mpi_world_rank()

    def visualize(self):
        self.c.visualize()
        self.visualize_count += 1
        if self.visualize_count == int(self.visualize_count_limit):
            self.video_manager.make_video()
            self.visualize_count_limit *= math.sqrt(2)

    def get_debug_information(self):
        return self.c.get_debug_information()

    def clear_output_directory(self):
        frames_dir = os.path.join(self.directory, 'frames')
        taichi.clear_directory_with_suffix(frames_dir, 'json')
        taichi.clear_directory_with_suffix(frames_dir, 'bgeo')
        taichi.clear_directory_with_suffix(frames_dir, 'obj')

    def simulate(self,
                 clear_output_directory=False,
                 print_profile_info=False,
                 frame_update=None,
                 update_frequency=1):
        if clear_output_directory:
            self.clear_output_directory()
        for i in range(self.num_frames):
            print('Simulating frame {}'.format(i))
            for k in range(update_frequency):
                if frame_update:
                    frame_update(self.get_current_time(),
                                 self.frame_dt / update_frequency)
                self.step(self.frame_dt / update_frequency)
            self.visualize()
            if print_profile_info:
                tc.core.print_profile_info()

    def add_articulation(self, **kwargs):
        kwargs['action'] = 'add_articulation'
        self.c.general_action(P(**kwargs))

    def action(self, **kwargs):
        self.c.general_action(P(**kwargs))