Exemple #1
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)
Exemple #2
0
 def lies_inside(self, location):
     lower, upper = math.batch_align([self.lower, self.upper], 1, location)
     bool_inside = (location >= lower) & (location <= upper)
     return math.all(bool_inside, axis=-1, keepdims=True)
Exemple #3
0
 def lies_inside(self, location):
     bool_inside = (location >= self.lower) & (location <= self.upper)
     return math.all(bool_inside, 'vector')
Exemple #4
0
 def __eq__(self, other):
     return isinstance(other,
                       Scene) and math.all(other._paths == self._paths)
Exemple #5
0
 def value_at(self, global_position):
     lower, upper = math.batch_align([self.lower, self.upper], 1,
                                     global_position)
     bool_inside = (global_position >= lower) & (global_position <= upper)
     bool_inside = math.all(bool_inside, axis=-1, keepdims=True)
     return math.to_float(bool_inside)
Exemple #6
0
def make_incompressible(velocity: Grid,
                        domain: Domain,
                        obstacles: tuple or list = (),
                        solve_params: math.LinearSolve = math.LinearSolve(
                            None, 1e-3),
                        pressure_guess: CenteredGrid = None):
    """
    Projects the given velocity field by solving for the pressure and subtracting its gradient.
    
    This method is similar to :func:`field.divergence_free()` but differs in how the boundary conditions are specified.

    Args:
      velocity: Vector field sampled on a grid
      domain: Used to specify boundary conditions
      obstacles: List of Obstacles to specify boundary conditions inside the domain (Default value = ())
      pressure_guess: Initial guess for the pressure solve
      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`

    """
    input_velocity = velocity
    active = domain.grid(
        HardGeometryMask(~union(*[obstacle.geometry
                                  for obstacle in obstacles])),
        extrapolation=domain.boundaries['active_extrapolation'])
    accessible = domain.grid(
        active, extrapolation=domain.boundaries['accessible_extrapolation'])
    hard_bcs = field.stagger(accessible,
                             math.minimum,
                             domain.boundaries['accessible_extrapolation'],
                             type=type(velocity))
    velocity = layer_obstacle_velocities(velocity * hard_bcs, obstacles).with_(
        extrapolation=domain.boundaries['near_vector_extrapolation'])
    div = divergence(velocity)
    if domain.boundaries[
            'near_vector_extrapolation'] == math.extrapolation.BOUNDARY:
        div -= field.mean(div)

    # Solve pressure

    def laplace(p):
        grad = gradient(p, type(velocity))
        grad *= hard_bcs
        grad = grad.with_(
            extrapolation=domain.boundaries['near_vector_extrapolation'])
        div = divergence(grad)
        lap = where(active, div, p)
        return lap

    pressure_guess = pressure_guess if pressure_guess is not None else domain.scalar_grid(
        0)
    converged, pressure, iterations = field.solve(laplace,
                                                  y=div,
                                                  x0=pressure_guess,
                                                  solve_params=solve_params,
                                                  constants=[active, hard_bcs])
    if math.all_available(converged) and not math.all(converged):
        raise AssertionError(
            f"pressure solve did not converge after {iterations} iterations\nResult: {pressure.values}"
        )
    # Subtract grad pressure
    gradp = field.gradient(pressure, type=type(velocity)) * hard_bcs
    velocity = (velocity -
                gradp).with_(extrapolation=input_velocity.extrapolation)
    return velocity, pressure, iterations, div
Exemple #7
0
 def lies_inside(self, location):
     bool_inside = (location >= self.lower) & (location <= self.upper)
     bool_inside = math.all(bool_inside, 'vector')
     bool_inside = math.any(
         bool_inside, self.shape.instance)  # union for instance dimensions
     return bool_inside
Exemple #8
0
 def __eq__(self, other):
     return isinstance(other, Sphere) \
            and self._shape == other.shape \
            and math.all(self._radius == other.radius) \
            and math.all(self._center == other.center)
Exemple #9
0
 def test_all(self):
     for backend in BACKENDS:
         with backend:
             math.assert_close(math.all(math.tensor([[False, True], [True, True]], spatial('y,x')), dim='x'), [False, True])
             math.assert_close(math.all(math.tensor([[False, True], [True, True]], spatial('y,x')), dim='x,y'), False)
             math.assert_close(math.all(math.tensor([[False, True], [True, True]], spatial('y,x'))), False)