Example #1
0
 def test_write_read(self):
     DOMAIN = Domain(x=32, y=32, boundaries=CLOSED)
     smoke = DOMAIN.scalar_grid(1)
     vel = DOMAIN.staggered_grid(2)
     # write
     scene = Scene.create(DIR)
     scene.write(smoke=smoke, vel=vel)
     self.assertEqual(1, len(scene.frames))
     self.assertEqual(1, len(scene.complete_frames))
     self.assertEqual(2, len(scene.fieldnames))
     # read single
     smoke_ = scene.read('smoke')
     vel_ = scene.read('vel')
     field.assert_close(smoke, smoke_)
     field.assert_close(vel, vel_)
     self.assertEqual(smoke.extrapolation, smoke_.extrapolation)
     self.assertEqual(vel.extrapolation, vel_.extrapolation)
     # read multiple
     smoke__, vel__ = scene.read(['smoke', 'vel'])  # deprecated
     field.assert_close(smoke, smoke__)
     field.assert_close(vel, vel__)
     smoke__, vel__ = scene.read('smoke', 'vel')
     field.assert_close(smoke, smoke__)
     field.assert_close(vel, vel__)
     scene.remove()
Example #2
0
def _test_advection(adv):
    domain = Domain(x=4, y=3)
    s = domain.scalar_grid(Noise())
    v = domain.vector_grid(Noise(vector=2))
    field.assert_close(s, adv(s, v, 0), adv(s, v * 0, 1))
    sv = domain.staggered_grid(Noise())
    field.assert_close(s, adv(s, sv, 0), adv(s, sv * 0, 1))
    field.assert_close(sv, adv(sv, sv, 0), adv(sv, sv * 0, 1))
Example #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 = domain.vector_grid(Noise(vector=2))
     field.assert_close(points, advect.runge_kutta_4(points, v, 0),
                        advect.runge_kutta_4(points, v * 0, 0))
     sv = domain.staggered_grid(Noise())
     field.assert_close(points, advect.runge_kutta_4(points, sv, 0),
                        advect.runge_kutta_4(points, sv * 0, 0))
Example #4
0
 def test_write_read_batch_batched_files(self):
     DOMAIN = Domain(x=32, y=32, boundaries=CLOSED)
     smoke = DOMAIN.scalar_grid(1) * math.random_uniform(count=2, config=3)
     vel = DOMAIN.staggered_grid(2) * math.random_uniform(count=2, vel=2)
     # write
     scene = Scene.create(DIR, count=2)
     scene.write({'smoke': smoke, 'vel': vel})
     # read batch
     smoke_ = scene.read('smoke')
     vel_ = scene.read('vel')
     field.assert_close(smoke, smoke_)
     field.assert_close(vel, vel_)
     scene.remove()
Example #5
0
    def test_trace_function(self):
        def f(x: StaggeredGrid, y: CenteredGrid):
            return x + (y >> x)

        ft = field.trace_function(f)
        domain = Domain(x=4, y=3)
        x = domain.staggered_grid(1)
        y = domain.vector_grid(1)

        res_f = f(x, y)
        res_ft = ft(x, y)
        self.assertEqual(res_f.shape, res_ft.shape)
        field.assert_close(res_f, res_ft)
Example #6
0
 def test_write_read_batch_duplicate(self):
     DOMAIN = Domain(x=32, y=32, boundaries=CLOSED)
     smoke = DOMAIN.scalar_grid(1) * math.random_uniform(count=2)
     vel = DOMAIN.staggered_grid(2) * math.random_uniform(count=2)
     # write
     scene = Scene.create(DIR, more=2)
     scene.write({'smoke': smoke, 'vel': vel})
     # read batch
     smoke_ = scene.read('smoke')
     vel_ = scene.read('vel')
     self.assertEqual(4, smoke_.shape.batch.volume)
     self.assertEqual(4, vel_.shape.batch.volume)
     field.assert_close(smoke, smoke_)
     field.assert_close(vel, vel_)
     scene.remove()
Example #7
0
 def test_make_incompressible_gradients_equal_tf_torch(self):
     DOMAIN = Domain(x=16, y=16, boundaries=OPEN, bounds=Box[0:100, 0:100])  # TODO CLOSED solve fails because div is not subtracted from dx
     velocity0 = DOMAIN.staggered_grid(Noise(vector=2))
     grads = []
     for backend in [TF_BACKEND, TORCH_BACKEND]:
         with backend:
             velocity = param = velocity0.with_(values=math.tensor(velocity0.values))
             with math.record_gradients(param.values):
                 solve = math.LinearSolve()
                 velocity, _, _, _ = fluid.make_incompressible(velocity, DOMAIN, solve_params=solve)
                 loss = field.l2_loss(velocity)
                 assert math.isfinite(loss)
                 grad = math.gradients(loss, param.values)
                 assert math.all(math.isfinite(grad))
                 grads.append(grad)
     math.assert_close(*grads, abs_tolerance=1e-5)
Example #8
0
    def test_gradient_function(self):
        def f(x: StaggeredGrid, y: CenteredGrid):
            pred = x + (y >> x)
            loss = field.l2_loss(pred)
            return loss

        domain = Domain(x=4, y=3)
        x = domain.staggered_grid(1)
        y = domain.vector_grid(1)

        with torch.TORCH_BACKEND:
            dx, = field.gradient_function(f)(x, y)
            self.assertIsInstance(dx, StaggeredGrid)
            loss, dx, dy = field.gradient_function(f, (0, 1),
                                                   get_output=True)(x, y)
            self.assertIsInstance(loss, math.Tensor)
            self.assertIsInstance(dx, StaggeredGrid)
            self.assertIsInstance(dy, CenteredGrid)
Example #9
0
    def test_gradient_function(self):
        def f(x: StaggeredGrid, y: CenteredGrid):
            pred = x + (y >> x)
            loss = field.l2_loss(pred)
            return loss

        domain = Domain(x=4, y=3)
        x = domain.staggered_grid(1)
        y = domain.vector_grid(1)

        for backend in BACKENDS:
            if backend.supports(Backend.gradients):
                with backend:
                    dx, = field.functional_gradient(f)(x, y)
                    self.assertIsInstance(dx, StaggeredGrid)
                    loss, dx, dy = field.functional_gradient(f, (0, 1), get_output=True)(x, y)
                    self.assertIsInstance(loss, math.Tensor)
                    self.assertIsInstance(dx, StaggeredGrid)
                    self.assertIsInstance(dy, CenteredGrid)
Example #10
0
 def test_custom_spatial_dims(self):
     domain = Domain(a=4, b=3)
     grid = domain.scalar_grid(1)
     self.assertEqual(math.shape(a=4, b=3), grid.shape)
     grid = domain.staggered_grid(1)
     self.assertEqual(math.shape(a=4, b=3, vector=2), grid.shape)
Example #11
0
 def test_domain_grid_memory_allocation(self):
     domain = Domain(x=10000, y=10000, z=10000, w=10000)
     grid = domain.scalar_grid()
     self.assertEqual((10000, ) * 4, grid.shape.sizes)
     sgrid = domain.staggered_grid()
     self.assertEqual((10000, 10000, 10000, 10000, 4), sgrid.shape.sizes)
Example #12
0
def make_incompressible(
    velocity: StaggeredGrid,
    domain: Domain,
    obstacles: tuple or list or StaggeredGrid = (),
    particles: PointCloud or None = None,
    solve_params: math.LinearSolve = math.LinearSolve(),
    pressure_guess: CenteredGrid = None
) -> Tuple[StaggeredGrid, CenteredGrid, math.Tensor, CenteredGrid,
           StaggeredGrid]:
    """
    Projects the given velocity field by solving for the pressure and subtracting its spatial_gradient.

    Args:
        velocity: Current velocity field as StaggeredGrid
        obstacles: Sequence of `phi.physics.Obstacle` objects or binary StaggeredGrid marking through-flow cell faces
        particles (Optional if occupation masks are provided): Pointcloud holding the current positions of the particles
        domain (Optional if occupation masks are provided): Domain object
        pressure_guess (Optional): Initial pressure guess as CenteredGrid
        solve_params: Parameters for the pressure solve

    Returns:
      velocity: divergence-free velocity of type `type(velocity)`
      pressure: solved pressure field, `CenteredGrid`
      iterations: Number of iterations required to solve for the pressure
      divergence: divergence field of input velocity, `CenteredGrid`
      occupation_mask: StaggeredGrid
    """
    points = particles.with_(values=math.wrap(1))
    occupied_centered = points >> domain.grid()
    occupied_staggered = points >> domain.staggered_grid()

    if isinstance(obstacles, StaggeredGrid):
        accessible = obstacles
    else:
        accessible = domain.accessible_mask(
            union(*[obstacle.geometry for obstacle in obstacles]),
            type=StaggeredGrid)

    # --- Extrapolation is needed to exclude border divergence from the `occupied_centered` mask and thus
    # from the pressure solve. If particles are randomly distributed, the `occupied_centered` mask
    # could sometimes include the divergence at the borders (due to single particles right at the edge
    # which temporarily deform the `occupied_centered` mask when moving into a new cell) which would then
    # get compensated by the pressure. This is unwanted for falling liquids and therefore prevented by this
    # extrapolation. ---
    velocity_field, _ = extrapolate_valid(velocity * occupied_staggered,
                                          occupied_staggered, 1)
    velocity_field *= accessible  # Enforces boundary conditions after extrapolation
    div = field.divergence(
        velocity_field
    ) * occupied_centered  # Multiplication with `occupied_centered` excludes border divergence from pressure solve

    def matrix_eq(p):
        return field.where(
            occupied_centered,
            field.divergence(
                field.spatial_gradient(p, type=StaggeredGrid) * accessible), p)

    converged, pressure, iterations = field.solve(matrix_eq,
                                                  div,
                                                  pressure_guess
                                                  or domain.grid(),
                                                  solve_params=solve_params)
    gradp = field.spatial_gradient(pressure,
                                   type=type(velocity_field)) * accessible
    return velocity_field - gradp, pressure, iterations, div, occupied_staggered
Example #13
0
 def test_sample_at(self):
     DOMAIN = Domain(x=4, y=3)
     field = AngularVelocity([0, 0])
     self.assertEqual(math.shape(vector=2), field.shape.channel)
     field >> DOMAIN.vector_grid()
     field >> DOMAIN.staggered_grid()