Exemple #1
0
 def test_domain_grid_from_function(self):
     grid = Domain(x=4, y=3).scalar_grid(lambda x: math.sum(x**2, 'vector'))
     math.assert_close(grid.values.x[0].y[0], 0.5)
     self.assertEqual(grid.shape.volume, 12)
     grid = Domain(
         x=4, y=3).scalar_grid(lambda x: math.ones(x.shape.non_channel))
     math.assert_close(grid.values, 1)
Exemple #2
0
 def test_falling_block_long(self):
     """ Tests if a block of liquid has a constant shape during free fall. """
     DOMAIN = Domain(x=32,
                     y=128,
                     boundaries=STICKY,
                     bounds=Box[0:32, 0:128])
     DT = 0.05
     ACCESSIBLE = DOMAIN.accessible_mask([], type=StaggeredGrid)
     PARTICLES = DOMAIN.distribute_points(union(Box[12:20,
                                                    110:120])) * (0, 0)
     extent = math.max(PARTICLES.points, dim='points') - math.min(
         PARTICLES.points, dim='points')
     state = dict(particles=PARTICLES,
                  domain=DOMAIN,
                  dt=DT,
                  accessible=ACCESSIBLE)
     for i in range(90):
         state = step(**state)
         curr_extent = math.max(state['particles'].points, dim='points') - \
                       math.min(state['particles'].points, dim='points')
         math.assert_close(curr_extent,
                           extent)  # shape of falling block stays the same
         assert math.max(state['particles'].points, dim='points')[1] < \
                math.max(PARTICLES.points, dim='points')[1]  # block really falls
         extent = curr_extent
Exemple #3
0
 def test_runge_kutta_4(self):
     domain = Domain(x=4, y=3)
     points = domain.distribute_points(domain.bounds, points_per_cell=2)
     v = CenteredGrid(Noise(vector=2), x=4, y=3)
     field.assert_close(points, advect.runge_kutta_4(points, v, 0),
                        advect.runge_kutta_4(points, v * 0, 0))
     sv = StaggeredGrid(Noise(), x=4, y=3)
     field.assert_close(points, advect.runge_kutta_4(points, sv, 0),
                        advect.runge_kutta_4(points, sv * 0, 0))
Exemple #4
0
 def test_domain_grid_from_constant(self):
     domain = Domain(x=4, y=3)
     # int / float
     grid = domain.scalar_grid(1)
     math.assert_close(grid.values, 1)
     # complex
     grid = domain.scalar_grid(1 + 1j)
     math.assert_close(grid.values, 1 + 1j)
     # NumPy
     grid = domain.scalar_grid(numpy.array(1))
     math.assert_close(grid.values, 1)
Exemple #5
0
    def test_symmetry(self):
        """ Tests the symmetry of a setup where a liquid block collides with 2 rotated obstacles. """
        SIZE = 64
        MID = SIZE / 2
        DOMAIN = Domain(x=SIZE,
                        y=SIZE,
                        boundaries=STICKY,
                        bounds=Box[0:SIZE, 0:SIZE])
        DT = 0.05
        OBSTACLE = union([
            Box[20:30, 10:12].rotated(math.tensor(20)),
            Box[34:44, 10:12].rotated(math.tensor(-20))
        ])
        ACCESSIBLE = DOMAIN.accessible_mask(OBSTACLE, type=StaggeredGrid)
        x_low = 26
        x_high = 38
        y_low = 40
        y_high = 50
        PARTICLES = DOMAIN.distribute_points(
            union(Box[x_low:x_high, y_low:y_high]), center=True) * (0, 0)

        x_num = int((x_high - x_low) / 2)
        y_num = y_high - y_low
        particles_per_cell = 8
        total = x_num * y_num

        state = dict(particles=PARTICLES,
                     domain=DOMAIN,
                     dt=DT,
                     accessible=ACCESSIBLE)
        for i in range(100):
            state = step(**state)
            particles = state['particles'].points
            left = particles.points[particles.vector[0] < MID]
            right = particles.points[particles.vector[0] > MID]
            self.assertEqual(left.points.size, right.points.size)
            mirrored = math.copy(right).numpy('points,vector')
            mirrored[:, 0] = 2 * MID - right[:, 0]
            smirrored = np.zeros_like(mirrored)
            # --- particle order of mirrored version differs from original one and must be fixed for MSE
            # (caused by ordering in phi.physics._boundaries _distribute_points) ---
            for p in range(particles_per_cell):
                for b in range(x_num):
                    smirrored[p * total + b * y_num:p * total + (b + 1) * y_num] = \
                        mirrored[(p + 1) * total - (b + 1) * y_num:(p + 1) * total - b * y_num]
            mse = np.square(smirrored - left.numpy('points,vector')).mean()
            if i < 45:
                assert mse == 0  # block was falling until this step, hits obstacles at step 46
            else:
                assert mse <= 1e-3  # error increases gradually after block and obstacles collide
Exemple #6
0
 def test_effects(self):
     world = World()
     fluid = world.add(Fluid(Domain(x=16, y=16)), physics=IncompressibleFlow())
     fan = world.add(Fan(Sphere((10, 8), 5), [-1, 0]))
     obstacle = world.add(Obstacle(Box[0:1, 0:1]))
     world.step(dt=1)
     world.step(dt=0.5)
     assert fluid.age == fan.age == obstacle.age == 1.5
Exemple #7
0
 def test_smoke_plume(self):
     world = World()
     world.batch_size = 3
     fluid = world.add(Fluid(Domain(x=16, y=16)), physics=IncompressibleFlow())
     inflow = world.add(Inflow(Sphere((8, 8), radius=4)))
     world.step()
     world.step(fluid)
     self.assertAlmostEqual(fluid.age, 2.0)
     self.assertAlmostEqual(inflow.age, 1.0)
Exemple #8
0
 def test_respect_boundaries(self):
     """ Tests if particles really get puhsed outside of obstacles and domain boundaries. """
     SIZE = 64
     DOMAIN = Domain(x=SIZE,
                     y=SIZE,
                     boundaries=STICKY,
                     bounds=Box[0:SIZE, 0:SIZE])
     OBSTACLE = Box[20:40, 10:30]
     PARTICLES = DOMAIN.distribute_points(
         union(Box[20:38, 20:50], Box[50:60, 10:50]), center=True) * (10, 0)
     PARTICLES = advect.points(PARTICLES, PARTICLES, 1)
     assert math.any(OBSTACLE.lies_inside(PARTICLES.points))
     assert math.any((~DOMAIN.bounds).lies_inside(PARTICLES.points))
     PARTICLES = flip.respect_boundaries(PARTICLES,
                                         DOMAIN, [OBSTACLE],
                                         offset=0.1)
     assert math.all(~OBSTACLE.lies_inside(PARTICLES.points))
     assert math.all(~(~DOMAIN.bounds).lies_inside(PARTICLES.points))
Exemple #9
0
    def test_block_and_pool(self):
        """ Tests if the impact of a block on a pool has no sideeffects (e.g. liquid explosion). """
        SIZE = 32
        DOMAIN = Domain(x=SIZE,
                        y=SIZE,
                        boundaries=STICKY,
                        bounds=Box[0:SIZE, 0:SIZE])
        DT = 0.05
        ACCESSIBLE = DOMAIN.accessible_mask([], type=StaggeredGrid)
        PARTICLES = DOMAIN.distribute_points(
            union(Box[:, :5], Box[12:18, 15:20])) * (0, 0)

        state = dict(particles=PARTICLES,
                     domain=DOMAIN,
                     dt=DT,
                     accessible=ACCESSIBLE)
        for i in range(100):
            state = step(**state)

        assert math.all(state['particles'].points.vector[1] < 15)
Exemple #10
0
 def test_single_particles(self):
     """ Tests if single particles at the boundaries and within the domain really fall down. """
     SIZE = 32
     DOMAIN = Domain(x=SIZE,
                     y=SIZE,
                     boundaries=STICKY,
                     bounds=Box[0:SIZE, 0:SIZE])
     DT = 0.05
     ACCESSIBLE = DOMAIN.accessible_mask([], type=StaggeredGrid)
     PARTICLES = DOMAIN.distribute_points(union(
         Box[0:1, 10:11], Box[31:32, 20:21], Box[10:11, 10:11]),
                                          points_per_cell=1) * (0, 0)
     self.assertEqual(PARTICLES.points.shape['points'].size, 3)
     state = dict(particles=PARTICLES,
                  domain=DOMAIN,
                  dt=DT,
                  accessible=ACCESSIBLE)
     for i in range(10):
         state = step(**state)
         assert math.all(state['particles'].points.vector[1] <
                         PARTICLES.points.vector[1])
         PARTICLES = state['particles']
Exemple #11
0
 def simulate(centers):
     world = World()
     fluid = world.add(Fluid(Domain(x=5, y=4, bounds=Box(0, [40, 32])),
                             buoyancy_factor=0.1,
                             batch_size=centers.shape[0]),
                       physics=IncompressibleFlow())
     world.add(Inflow(Sphere(center=centers, radius=3), rate=0.2))
     world.add(Fan(Sphere(center=centers, radius=5), acceleration=[1.0, 0]))
     world.step(dt=1.5)
     world.step(dt=1.5)
     world.step(dt=1.5)
     assert not math.close(fluid.density.values, 0)
     print()
     return fluid.density.values.batch[0], fluid.velocity.values.batch[0]
Exemple #12
0
    def test_pool(self):
        """ Tests if a pool of liquid at the bottom stays constant over time. """
        SIZE = 32
        DOMAIN = Domain(x=SIZE,
                        y=SIZE,
                        boundaries=STICKY,
                        bounds=Box[0:SIZE, 0:SIZE])
        DT = 0.05
        ACCESSIBLE = DOMAIN.accessible_mask([], type=StaggeredGrid)
        PARTICLES = DOMAIN.distribute_points(union(Box[:, :10])) * (0, 0)

        state = dict(particles=PARTICLES,
                     domain=DOMAIN,
                     dt=DT,
                     accessible=ACCESSIBLE)
        for i in range(100):
            state = step(**state)

        occupied_start = PARTICLES.with_values(1) @ DOMAIN.scalar_grid()
        occupied_end = state['particles'].with_values(1) @ DOMAIN.scalar_grid()
        math.assert_close(occupied_start.values, occupied_end.values)
        math.assert_close(PARTICLES.points,
                          state['particles'].points,
                          abs_tolerance=1e-3)
Exemple #13
0
 def test_direct_fluid(self):
     fluid = Fluid(Domain(x=16, y=16))
     fluid2 = IncompressibleFlow().step(fluid)
     assert fluid2.age == 1.0
     assert fluid.age == 0.0
     assert fluid2.name == fluid.name
Exemple #14
0

scene = Scene.create(parent_directory=params['output'])  # phiflow scene

log.addHandler(logging.FileHandler(os.path.normpath(scene.path) + '/run.log'))
log.info(params)
log.info('tensorflow-{} ({}, {}); keras-{} ({})'.format(
    tf.__version__, tf.sysconfig.get_include(), tf.sysconfig.get_lib(),
    keras.__version__, keras.__path__))

if params['output']:
    with open(os.path.normpath(scene.path) + '/params.pickle', 'wb') as f:
        pickle.dump(params, f)

domain = Domain(y=params['res'] * 2,
                x=params['res'],
                bounds=Box[0:params['len'] * 2, 0:params['len']],
                boundaries=OPEN)

# init density & velocity
d0 = phi.field.read(params['initdH']).at(
    domain.scalar_grid()) if params['initdH'] else domain.scalar_grid(0)

if params['initvH']:
    v0 = phi.field.read(params['initvH']).at(domain.staggered_grid())

else:
    vv = np.ones(domain.staggered_grid().vector['y'].shape.sizes
                 )  # warm start - initialize flow to 1 along y everywhere
    uu = np.zeros(domain.staggered_grid().vector['x'].shape.sizes)
    uu[uu.shape[0] // 2 + 10:uu.shape[0] // 2 + 20,
       uu.shape[1] // 2 - 2:uu.shape[1] // 2 +
Exemple #15
0
""" Point Cloud Demo
Demonstrates working with PointCloud objects and plotting them.
"""

from phi.physics._boundaries import Domain, STICKY as CLOSED
from phi.flow import *

DOMAIN = Domain(x=64, y=64, boundaries=CLOSED, bounds=Box(x=100, y=100))
# points = DOMAIN.points([(1, 1), (20, 20)], color=['#ba0a04', '#344feb'])

points1 = DOMAIN.points((1, 1), color='#ba0a04')
points2 = DOMAIN.points((20, 20), color='#344feb')
# points = points1 & points2
points = field.concat([points1, points2], instance('points'))

# Advection
velocity = DOMAIN.vector_grid([-1, 1])
points = advect.advect(points, velocity, 10)  # RK4
points = advect.advect(points, points * (-1, 1), -5)  # Euler

# Grid sampling
scattered_data = field.sample(points, DOMAIN.cells)
scattered_grid = points @ DOMAIN.vector_grid()
scattered_sgrid = points @ DOMAIN.staggered_grid()

view(namespace=globals())
Exemple #16
0
        v_hi = [
            math.concat([
                self.dataPreloaded[self.dataSims[self.epoch[self.batchIdx + i][
                    self.stepIdx][0]]][max([
                        0, self.epoch[self.batchIdx + i][self.stepIdx][1] -
                        j * with_skip
                    ])][2] for i in range(self.batchSize)
            ],
                        axis=0) for j in range(previous_frames)
        ]
        # TODO: additional channels
        return [d_hi, v_hi]


domain = Domain(y=params['res'] * 2,
                x=params['res'],
                bounds=Box[0:params['len'] * 2, 0:params['len']],
                boundaries=OPEN)
simulator_lo = KarmanFlow(domain=domain)

dataset = PhifDataset(domain=domain,
                      dirpath=params['train'],
                      num_frames=params['simsteps'],
                      num_sims=params['nsims'],
                      batch_size=params['sbatch'],
                      print_fn=log.info,
                      skip_preprocessing=params['skip_ds'])
if params['only_ds']: exit(0)

if params['pretf']:
    with open(os.path.dirname(params['pretf']) + '/stats.pickle', 'rb') as f:
        ld_stats = pickle.load(f)
Exemple #17
0
 def test_domain_grid_from_field(self):
     large_grid = Domain(x=4, y=3).grid(Noise())
     small_grid = Domain(x=3, y=2).grid(large_grid)
     math.assert_close(large_grid.values.x[:-1].y[:-1], small_grid.values)
Exemple #18
0
""" FLIP simulation for liquids

A liquid block collides with a rotated obstacle and falls into a liquid pool.
"""

from phi.physics._boundaries import Domain, STICKY as CLOSED
from phi.flow import *
# from phi.torch.flow import *
# from phi.tf.flow import *
# from phi.jax.flow import *

DOMAIN = Domain(x=64, y=64, boundaries=CLOSED, bounds=Box(x=64, y=64))
GRAVITY = math.tensor([0, -9.81])
DT = 0.1
OBSTACLE = Box(x=(1, 25), y=(30, 33)).rotated(-20)
ACCESSIBLE_MASK = field.stagger(
    CenteredGrid(~OBSTACLE, extrapolation.ZERO, x=64, y=64), math.minimum,
    extrapolation.ZERO)
_OBSTACLE_POINTS = DOMAIN.distribute_points(OBSTACLE,
                                            color='#000000',
                                            points_per_cell=1,
                                            center=True)  # only for plotting

particles = DOMAIN.distribute_points(
    union(Box(x=(15, 30), y=(50, 60)), Box(x=None, y=(-INF, 5)))) * (0, 0)
velocity = particles @ DOMAIN.staggered_grid()
pressure = DOMAIN.scalar_grid()
scene = particles & _OBSTACLE_POINTS * (0, 0)  # only for plotting

for _ in view('scene,velocity,pressure',
              display='scene',
Exemple #19
0
        def test_demo_vs_numpy(self):
            dt = 0.1
            # Physical parameters
            L = 4 * 2 * np.pi  # 2 * np.pi / 0.15  # 4*2*np.pi#/0.15
            c1 = 5  # 0.01
            # Numerical Parameters
            grid_pts = 64
            nu = 0  # 1e-8
            N = 0  # 3
            arakawa_coeff = 0
            kappa_coeff = 0
            # Derived Parameters
            dx = L / grid_pts
            k0 = 2 * np.pi / L
            # Get input data
            rnd_noise = np.random.rand(grid_pts * grid_pts).reshape(
                grid_pts, grid_pts)
            sine = get_2d_sine((grid_pts, grid_pts), L)
            init_values = sine / 1000
            density_coeff = 1
            omega_coeff = -1 / 2
            phi_coeff = -1 / 2
            x = grid_pts
            y = grid_pts
            params = dict(c1=c1,
                          nu=nu,
                          N=N,
                          arakawa_coeff=arakawa_coeff,
                          kappa_coeff=kappa_coeff)
            # NumPy reference
            hw = HW(
                c1=c1,
                nu=nu,
                N=N,
                arakawa_coeff=arakawa_coeff,
                kappa_coeff=kappa_coeff,
                debug=False,
            )
            hw_state_numpy = Namespace(
                density=init_values * density_coeff,
                omega=init_values * omega_coeff,
                phi=init_values * phi_coeff,
                age=0,
                dx=dx,
            )
            # Phi version
            domain = Domain(x=x,
                            y=y,
                            boundaries=PERIODIC,
                            bounds=Box[0:L, 0:L])
            hw_state_phi = Namespace(
                density=domain.grid(
                    math.tensor(init_values * density_coeff, spatial('x, y'))),
                omega=domain.grid(
                    math.tensor(init_values * omega_coeff, spatial('x, y'))),
                phi=domain.grid(
                    math.tensor(init_values * phi_coeff, spatial('x, y'))),
                # domain=domain,
                age=0,
                dx=dx,
            )
            from functools import partial

            get_phi = partial(get_domain_phi, domain=domain)
            rk4_step2 = partial(rk4_step, params=params, get_phi=get_phi)

            # Run
            def compare(iterable):
                for k in iterable[0].keys():
                    compare = []
                    for state in iterable:
                        if isinstance(state[k], field._grid.Grid):
                            val = state[k].values.numpy(order="x,y,z")[0]
                        else:
                            val = state[k]
                        compare.append(val)
                    assert len(compare) == 2
                    print(f"  {k:<7}:" +
                          f"  {np.max(np.abs(compare[0]-compare[1])):.7f}" +
                          f"  {np.array_equal(*compare)}" +
                          f"  {np.max(np.abs(compare[0]-compare[1])):.2g}")
                return True

            np_times = []
            phi_times = []
            for i in range(0, STEPS + 1):
                print(f"step {i:>3} {i*dt:>12.7f}")
                # Numpy
                t0 = time.time()
                hw_state_numpy = hw.rk4_step(hw_state_numpy, dt=dt)
                np_time = time.time() - t0
                np_times.append(np_time)
                # Phi
                t0 = time.time()
                hw_state_phi = rk4_step2(dt=dt, **hw_state_phi)
                phi_time = time.time() - t0
                phi_times.append(phi_time)
                compare([hw_state_numpy, hw_state_phi])
                # if i % 100 == 0:
                #    plot({'numpy': hw_state_numpy.density,
                #          'phi': hw_state_phi.density.values.numpy(order='zyx')[0],
                #          'diff': hw_state_numpy.density - hw_state_phi.density.values.numpy(order='zyx')[0]},
                #         title=f"step: {i}")
                # assert np.allclose(hw_state_numpy.density, hw_state_phi.density.values.numpy(order='zyx')[0])
            print(f"Comparison | NumPy      | PhiFlow")

            def get_str(name, func, vals):
                return " | ".join([
                    f"{name:<10}",
                    f"{func(vals[0]):<10.4f}",
                    f"{func(vals[1]):<10.4f}",
                ])

            print(get_str("Mean (s)", np.mean, (np_times, phi_times)))
            print(get_str("Median (s)", np.median, (np_times, phi_times)))
            print(get_str("Min (s)", np.min, (np_times, phi_times)))
            print(get_str("Max (s)", np.max, (np_times, phi_times)))
Exemple #20
0
 def test_properties_dict(self):
     world = World()
     world.add(Fluid(Domain(x=16, y=16)), physics=IncompressibleFlow())
     world.add(Inflow(Sphere((8, 8), radius=4)))
     world.add(Fan(Sphere((10, 8), 5), [-1, 0]))
     struct.properties_dict(world.state)
Exemple #21
0
 def test_domain_grid_from_tensor(self):
     domain = Domain(x=4, y=3)
     grid = domain.vector_grid(Noise(vector=2))
     grid2 = domain.vector_grid(grid.values)
     math.assert_close(grid.values, grid2.values)
Exemple #22
0
 def test_custom_spatial_dims(self):
     domain = Domain(a=4, b=3)
     grid = domain.scalar_grid(1)
     self.assertEqual(spatial(a=4, b=3), grid.shape)
     grid = domain.staggered_grid(1)
     self.assertEqual(spatial(a=4, b=3) & channel(vector=2), grid.shape)
"""
Profiles the common fluid operations advection and pressure solve.
The profile is stored in the working directory and can be viewed with e.g. with Google chrome.
"""

from phi.physics._boundaries import Domain, STICKY as CLOSED
from phi.flow import *
# from phi.torch.flow import *
# from phi.tf.flow import *
# from phi.jax.flow import *

DOMAIN = Domain(x=128, y=128, boundaries=CLOSED, bounds=Box(x=100, y=100))
velocity = DOMAIN.staggered_grid(Noise(vector=2))
pressure = DOMAIN.scalar_grid(0)

with backend.profile(save=f'navier_stokes_{backend.default_backend()}.json'):
    velocity = advect.semi_lagrangian(velocity, velocity, dt=1)
    # velocity, pressure = fluid.make_incompressible(velocity, DOMAIN, pressure_guess=pressure)
Exemple #24
0
 def test_advect_points(self):
     domain = Domain(x=4, y=3)
     v = domain.distribute_points(domain.bounds,
                                  points_per_cell=2) * (1, -1)
     field.assert_close(v, advect.points(v, v, 0),
                        advect.points(v, v * 0, 0))