Example #1
0
    def at(directory: str or tuple or list or math.Tensor or 'Scene', id: int or math.Tensor or None = None) -> 'Scene':
        """
        Creates a `Scene` for an existing directory.

        See Also:
            `Scene.create()`, `Scene.list()`.

        Args:
            directory: Either directory containing scene folder if `id` is given, or scene path if `id=None`.
            id: (Optional) Scene `id`, will be determined from `directory` if not specified.

        Returns:
            `Scene` object for existing scene.
        """
        if isinstance(directory, Scene):
            assert id is None, f"Got id={id} but directory is already a Scene."
            return directory
        if isinstance(directory, (tuple, list)):
            directory = math.wrap(directory, batch('scenes'))
        directory = math.map(lambda d: expanduser(d), math.wrap(directory))
        if id is None:
            paths = directory
        else:
            id = math.wrap(id)
            paths = math.map(lambda d, i: join(d, f"sim_{i:06d}"), directory, id)
        # test all exist
        for path in math.flatten(paths):
            if not isdir(path):
                raise IOError(f"There is no scene at '{path}'")
        return Scene(paths)
Example #2
0
def read_single_field(file: str, convert_to_backend=True) -> SampledField:
    stored = np.load(file, allow_pickle=True)
    ftype = stored['field_type']
    implemented_types = ('CenteredGrid', 'StaggeredGrid')
    if ftype in implemented_types:
        data = stored['data']
        dim_item_names = stored.get('dim_item_names',
                                    (None, ) * len(data.shape))
        data = NativeTensor(
            data,
            math.Shape(data.shape, tuple(stored['dim_names']),
                       tuple(stored['dim_types']), tuple(dim_item_names)))
        if convert_to_backend:
            data = math.tensor(data, convert=convert_to_backend)
        bounds_item_names = stored.get('bounds_item_names', (None, ) *
                                       len(stored['lower'] + stored['upper']))
        lower = math.wrap(
            stored['lower'], math.channel(vector=tuple(bounds_item_names))
        ) if stored['lower'].ndim > 0 else math.wrap(stored['lower'])
        upper = math.wrap(stored['upper'],
                          math.channel(vector=tuple(bounds_item_names)))
        extrapolation = math.extrapolation.from_dict(
            stored['extrapolation'][()])
        if ftype == 'CenteredGrid':
            return CenteredGrid(data,
                                bounds=geom.Box(lower, upper),
                                extrapolation=extrapolation)
        elif ftype == 'StaggeredGrid':
            data_ = unstack_staggered_tensor(data, extrapolation)
            return StaggeredGrid(data_,
                                 bounds=geom.Box(lower, upper),
                                 extrapolation=extrapolation)
    raise NotImplementedError(f"{ftype} not implemented ({implemented_types})")
Example #3
0
    def test_tensor_like(self):
        class Success(Exception):
            pass

        class MyObjV:
            def __init__(self, x):
                self.x = x

            def __value_attrs__(self):
                return 'x',

            def __with_tattrs__(self, **tattrs):
                math.assert_close(tattrs['x'], 1)
                raise Success

        class MyObjT:
            def __init__(self, x1, x2):
                self.x1 = x1
                self.x2 = x2

            def __variable_attrs__(self):
                return 'x1', 'x2'

        v = MyObjV(math.wrap(0))
        t = MyObjT(math.wrap(0), math.wrap(1))
        self.assertIsInstance(v, math.TensorLike)
        self.assertIsInstance(t, math.TensorLike)
        try:
            math.cos(v)
        except Success:
            pass
        try:
            math.cos(t)
        except AssertionError:
            pass
Example #4
0
 def test_downsample2x(self):
     meshgrid = math.meshgrid(x=(0, 1, 2, 3), y=(0, -1, -2))
     half_size = math.downsample2x(meshgrid, extrapolation.BOUNDARY)
     math.print(meshgrid, 'Full size')
     math.print(half_size, 'Half size')
     math.assert_close(half_size.vector[0], wrap([[0.5, 2.5], [0.5, 2.5]], spatial('y,x')))
     math.assert_close(half_size.vector[1], wrap([[-0.5, -0.5], [-2, -2]], spatial('y,x')))
Example #5
0
    def points(self,
               points: Tensor or Number or tuple or list,
               radius: Tensor or float or int or None = None,
               extrapolation: math.Extrapolation = None,
               color: str or Tensor or tuple or list or None = None) -> PointCloud:
        """
        Create a `phi.field.PointCloud` from the given `points`.
        The created field has no channel dimensions and all points carry the value `1`.

        Args:
            points: point locations in physical units
            radius: (optional) size of the particles
            extrapolation: (optional) extrapolation to use, defaults to extrapolation.ZERO
            color: (optional) color used when plotting the points

        Returns:
            `phi.field.PointCloud` object
        """
        extrapolation = extrapolation or math.extrapolation.ZERO
        if radius is None:
            radius = math.mean(self.bounds.size) * 0.005
        # --- Parse points: tuple / list ---
        if isinstance(points, (tuple, list)):
            if len(points) == 0:  # no points
                points = math.zeros(points=0, vector=1)
            elif isinstance(points[0], Number):  # single point
                points = math.wrap([points], 'points, vector')
            else:
                points = math.wrap(points, 'points, vector')
        elements = Sphere(points, radius)
        return PointCloud(elements, math.ones(), extrapolation, add_overlapping=False, bounds=self.bounds, color=color)
Example #6
0
 def test_scatter_add_2d(self):
     for backend in BACKENDS:
         with backend:
             base = math.ones(spatial(x=3, y=2))
             indices = math.wrap([(0, 0), (0, 0), (0, 1), (2, 1)], instance('points'), channel('vector'))
             values = math.wrap([11, 11, 12, 13], instance('points'))
             updated = math.scatter(base, indices, values, mode='add', outside_handling='undefined')
             math.assert_close(updated, math.tensor([[23, 1, 1], [13, 1, 14]], spatial('y,x')))
Example #7
0
 def test_plot_multiple(self):
     grid = CenteredGrid(Noise(batch(b=2)), 0, Box[0:1, 0:1], x=50, y=10)
     grid2 = CenteredGrid(grid, 0, Box[0:2, 0:1], x=20, y=50)
     points = wrap([(.2, .4), (.9, .8)], instance('points'),
                   channel('vector'))
     cloud = PointCloud(Sphere(points, radius=0.1), bounds=Box(0, [1, 1]))
     titles = math.wrap([['b=0', 'b=0', 'points'], ['b=1', 'b=1', '']],
                        spatial('rows,cols'))
     self._test_plot(grid, grid2, cloud, row_dims='b', title=titles)
Example #8
0
 def test_scatter_update_1d_batched(self):
     for backend in BACKENDS:
         with backend:
             # Only base batched
             base = math.zeros(spatial(x=4)) + math.tensor([0, 1])
             indices = math.wrap([1, 2], instance('points'))
             values = math.wrap([11, 12], instance('points'))
             updated = math.scatter(base, indices, values, mode='update', outside_handling='undefined')
             math.assert_close(updated, math.tensor([(0, 1), (11, 11), (12, 12), (0, 1)], spatial('x'), channel('vector')), msg=backend.name)
             # Only values batched
             base = math.ones(spatial(x=4))
             indices = math.wrap([1, 2], instance('points'))
             values = math.wrap([[11, 12], [-11, -12]], batch('batch'), instance('points'))
             updated = math.scatter(base, indices, values, mode='update', outside_handling='undefined')
             math.assert_close(updated, math.tensor([[1, 11, 12, 1], [1, -11, -12, 1]], batch('batch'), spatial('x')), msg=backend.name)
             # Only indices batched
             base = math.ones(spatial(x=4))
             indices = math.wrap([[0, 1], [1, 2]], batch('batch'), instance('points'))
             values = math.wrap([11, 12], instance('points'))
             updated = math.scatter(base, indices, values, mode='update', outside_handling='undefined')
             math.assert_close(updated, math.tensor([[11, 12, 1, 1], [1, 11, 12, 1]], batch('batch'), spatial('x')), msg=backend.name)
             # Everything batched
             base = math.zeros(spatial(x=4)) + math.tensor([0, 1], batch('batch'))
             indices = math.wrap([[0, 1], [1, 2]], batch('batch'), instance('points'))
             values = math.wrap([[11, 12], [-11, -12]], batch('batch'), instance('points'))
             updated = math.scatter(base, indices, values, mode='update', outside_handling='undefined')
             math.assert_close(updated, math.tensor([[11, 12, 0, 0], [1, -11, -12, 1]], batch('batch'), spatial('x')), msg=backend.name)
Example #9
0
 def test_scatter_1d(self):
     for backend in BACKENDS:
         with backend:
             base = math.ones(spatial(x=4))
             indices = math.wrap([1, 2], instance('points'))
             values = math.wrap([11, 12], instance('points'))
             updated = math.scatter(base, indices, values, mode='update', outside_handling='undefined')
             math.assert_close(updated, [1, 11, 12, 1])
             updated = math.scatter(base, indices, values, mode='add', outside_handling='undefined')
             math.assert_close(updated, [1, 12, 13, 1])
             # with vector dim
             indices = math.expand(indices, channel(vector=1))
             updated = math.scatter(base, indices, values, mode='update', outside_handling='undefined')
             math.assert_close(updated, [1, 11, 12, 1])
Example #10
0
 def __init__(self,
              location: math.Tensor or tuple or list or Number,
              strength: math.Tensor or Number = 1.0,
              falloff: Callable = None,
              component: str = None):
     location = math.wrap(location)
     strength = math.wrap(strength)
     assert location.shape.channel.names == ('vector',), "location must have a single channel dimension called 'vector'"
     assert location.shape.spatial.is_empty, "location tensor cannot have any spatial dimensions"
     self.location = location
     self.strength = strength
     self.falloff = falloff
     self.component = component
     spatial_names = [GLOBAL_AXIS_ORDER.axis_name(i, location.vector.size) for i in range(location.vector.size)]
     self._shape = location.shape & spatial(**{dim: 1 for dim in spatial_names})
Example #11
0
 def upsample_apply(params, inputs, **kwargs):
     x = math.wrap(
         inputs, math.batch('batch'),
         *[math.spatial(f'{i}') for i in range(len(inputs.shape) - 2)],
         math.channel('vector'))
     x = math.upsample2x(x)
     return x.native(x.shape)
Example #12
0
    def __init__(self, elements: Geometry,
                 values: Any = 1,
                 extrapolation=math.extrapolation.ZERO,
                 add_overlapping=False,
                 bounds: Box = None,
                 color: str or Tensor or tuple or list or None = None):
        """
        A point cloud consists of elements at arbitrary locations.
        A value or vector is associated with each element.

        Outside of elements, the value of the field is determined by the extrapolation.

        All points belonging to one example must be listed in the 'points' dimension.

        Unlike with GeometryMask, the elements of a PointCloud are assumed to be small.
        When sampling this field on a grid, scatter functions may be used.

        See the `phi.field` module documentation at https://tum-pbs.github.io/PhiFlow/Fields.html

        Args:
          elements: Geometry object specifying the sample points and sizes
          values: values corresponding to elements
          extrapolation: values outside elements
          add_overlapping: True: values of overlapping geometries are summed. False: values between overlapping geometries are interpolated
          bounds: (optional) size of the fixed domain in which the points should get visualized. None results in max and min coordinates of points.
          color: (optional) hex code for color or tensor of colors (same length as elements) in which points should get plotted.
        """
        SampledField.__init__(self, elements, values, extrapolation)
        self._add_overlapping = add_overlapping
        assert bounds is None or isinstance(bounds, Box), 'Invalid bounds.'
        self._bounds = bounds
        assert 'points' in self.shape, "Cannot create PointCloud without 'points' dimension. Add it either to elements or to values as batch dimension."
        if color is None:
            color = '#0060ff'
        self._color = math.wrap(color, names='points') if isinstance(color, (tuple, list)) else math.wrap(color)
Example #13
0
 def test_box_product(self):
     a = Box(x=4)
     b = Box(y=3).shifted(math.wrap(1))
     ab = a * b
     self.assertEqual(2, ab.spatial_rank)
     math.assert_close(ab.size, (4, 3))
     math.assert_close(ab.lower, (0, 1))
Example #14
0
    def list(parent_directory: str,
             name='sim',
             include_other: bool = False,
             dim: Shape or None = None) -> 'Scene' or tuple:
        """
        Lists all scenes inside the given directory.

        See Also:
            `Scene.at()`, `Scene.create()`.

        Args:
            parent_directory: Directory that contains scene folders.
            name: Name of the directory (excluding index). Default is `'sim'`.
            include_other: Whether folders that do not match the scene format should also be treated as scenes.
            dim: Stack dimension. If None, returns tuple of `Scene` objects. Otherwise, returns a scene batch with this dimension.

        Returns:
            `tuple` of scenes.
        """
        parent_directory = expanduser(parent_directory)
        abs_dir = abspath(parent_directory)
        if not isdir(abs_dir):
            return ()
        names = [sim for sim in os.listdir(abs_dir) if sim.startswith(f"{name}_") or (include_other and isdir(join(abs_dir, sim)))]
        if dim is None:
            return tuple(Scene(join(parent_directory, n)) for n in names)
        else:
            paths = math.wrap([join(parent_directory, n) for n in names], dim)
            return Scene(paths)
Example #15
0
 def __init__(self, geometry: Geometry, angle: float or math.Tensor):
     if isinstance(geometry, RotatedGeometry):
         warnings.warn(
             'Using RotatedGeometry of RotatedGeometry. Consider simplifying your setup.'
         )
     self._geometry = geometry
     self._angle = math.wrap(angle)
Example #16
0
 def __getitem__(self, item: dict):
     bounds = self._bounds
     dx = self.size
     gather_dict = {}
     for dim, selection in item.items():
         if dim in self._resolution:
             if isinstance(selection, int):
                 start = selection
                 stop = selection + 1
             elif isinstance(selection, slice):
                 start = selection.start or 0
                 stop = selection.stop or self.resolution.get_size(dim)
                 if stop < 0:
                     stop += self.resolution.get_size(dim)
                 assert selection.step is None or selection.step == 1
             else:
                 raise ValueError(f"Illegal selection: {item}")
             dim_mask = math.wrap(self.resolution.mask(dim))
             lower = bounds.lower + start * dim_mask * dx
             upper = bounds.upper + (
                 stop - self.resolution.get_size(dim)) * dim_mask * dx
             bounds = Box(lower, upper)
             gather_dict[dim] = slice(start, stop)
     resolution = self._resolution.after_gather(gather_dict)
     return GridCell(resolution, bounds)
Example #17
0
def tensor_as_field(t: Tensor):
    """
    Interpret a `Tensor` as a `CenteredGrid` or `PointCloud` depending on its dimensions.

    Unlike the `CenteredGrid` constructor, this function will have the values sampled at integer points for each spatial dimension.

    Args:
        t: `Tensor` with either `spatial` or `instance` dimensions.

    Returns:
        `CenteredGrid` or `PointCloud`
    """
    if spatial(t):
        assert not instance(
            t
        ), f"Cannot interpret tensor as Field because it has both spatial and instance dimensions: {t.shape}"
        bounds = Box(-0.5, math.wrap(spatial(t), channel('vector')) - 0.5)
        return CenteredGrid(t, 0, bounds=bounds)
    if instance(t):
        assert not spatial(
            t
        ), f"Cannot interpret tensor as Field because it has both spatial and instance dimensions: {t.shape}"
        assert 'vector' in t.shape, f"Cannot interpret tensor as PointCloud because it has not vector dimension."
        point_count = instance(t).volume
        bounds = data_bounds(t)
        radius = math.vec_length(
            bounds.size) / (1 + point_count**(1 / t.vector.size))
        return PointCloud(Sphere(t, radius=radius))
Example #18
0
 def __init__(self,
              center: Tensor = None,
              radius: float or Tensor = None,
              **center_: float or Tensor):
     """
     Args:
         center: Sphere center as `Tensor` with `vector` dimension.
             The spatial dimension order should be specified in the `vector` dimension via item names.
         radius: Sphere radius as `float` or `Tensor`
         **center_: Specifies center when the `center` argument is not given. Center position by dimension, e.g. `x=0.5, y=0.2`.
     """
     if center is not None:
         if not isinstance(center, Tensor):
             warnings.warn(
                 f"constructor Sphere({type(center)}) is deprecated. Use Sphere(Tensor) or Sphere(**center_) instead.",
                 DeprecationWarning)
             self._center = wrap(center)
         else:
             self._center = center
         assert 'vector' in self._center.shape, f"Sphere.center must have a 'vector' dimension. Use the syntax x=0.5."
     else:
         self._center = math.wrap(
             tuple(center_.values()),
             math.channel(vector=tuple(center_.keys())))
         # self._center = wrap(math.spatial(**center_), math.channel('vector'))
     assert radius is not None, "radius must be specified."
     self._radius = wrap(radius)
Example #19
0
    def __init__(self,
                 resolution: math.Shape = math.EMPTY_SHAPE,
                 boundaries: dict or tuple or list = OPEN,
                 bounds: Box = None,
                 **resolution_):
        """
        The Domain specifies the grid resolution, physical size and boundary conditions of a simulation.

        It provides convenience methods for creating Grids fitting the domain, e.g. `grid()`, `vector_grid()` and `staggered_grid()`.

        Also see the `phi.physics` module documentation at https://tum-pbs.github.io/PhiFlow/Physics.html

        Args:
          resolution: grid dimensions as Shape or sequence of integers. Alternatively, dimensions can be specified directly as kwargs.
          boundaries: specifies the extrapolation modes of grids created from this Domain.
            Default materials include OPEN, CLOSED, PERIODIC.
            To specify boundary conditions per face of the domain, pass a sequence of boundaries or boundary pairs (lower, upper)., e.g. [CLOSED, (CLOSED, OPEN)].
            See https://tum-pbs.github.io/PhiFlow/Physics.html#boundary-conditions .
          bounds: physical size of the domain. If not provided, the size is equal to the resolution (unit cubes).
        """
        self.resolution: math.Shape = spatial_shape(
            resolution) & spatial_shape(resolution_)
        """ Grid dimensions as `Shape` object containing spatial dimensions only. """
        self.boundaries: dict = _create_boundary_conditions(
            boundaries, self.resolution.names)
        """ Outer boundary conditions. """
        self.bounds: Box = Box(0, math.wrap(
            self.resolution, names='vector')) if bounds is None else bounds
        """ Physical dimensions of the domain. """
Example #20
0
 def __init__(self,
              lower: Tensor or float or int = None,
              upper: Tensor or float or int = None,
              **size: int or Tensor):
     """
     Args:
       lower: physical location of lower corner
       upper: physical location of upper corner
       **size: Upper l
     """
     if lower is not None:
         self._lower = wrap(lower)
     if upper is not None:
         self._upper = wrap(upper)
     else:
         lower = []
         upper = []
         for item in size.values():
             if isinstance(item, (tuple, list)):
                 assert len(
                     item
                 ) == 2, f"Box kwargs must be either dim=upper or dim=(lower,upper) but got {item}"
                 lo, up = item
                 lower.append(lo)
                 upper.append(up)
             elif item is None:
                 lower.append(-INF)
                 upper.append(INF)
             else:
                 lower.append(0)
                 upper.append(item)
         lower = [-INF if l is None else l for l in lower]
         upper = [INF if u is None else u for u in upper]
         self._upper = math.wrap(upper,
                                 math.channel(vector=tuple(size.keys())))
         self._lower = math.wrap(lower,
                                 math.channel(vector=tuple(size.keys())))
     vector_shape = self._lower.shape & self._upper.shape
     self._lower = math.expand(self._lower, vector_shape)
     self._upper = math.expand(self._upper, vector_shape)
     if self.size.vector.item_names is None:
         warnings.warn(
             "Creating a Box without item names prevents certain operations like project()",
             DeprecationWarning,
             stacklevel=2)
Example #21
0
def assert_close(*fields: SampledField or math.Tensor or Number,
                 rel_tolerance: float = 1e-5,
                 abs_tolerance: float = 0):
    """ Raises an AssertionError if the `values` of the given fields are not close. See `phi.math.assert_close()`. """
    f0 = next(filter(lambda t: isinstance(t, SampledField), fields))
    values = [(f >> f0).values if isinstance(f, SampledField) else math.wrap(f)
              for f in fields]
    math.assert_close(*values,
                      rel_tolerance=rel_tolerance,
                      abs_tolerance=abs_tolerance)
Example #22
0
 def test_overlay(self):
     grid = CenteredGrid(Noise(),
                         extrapolation.ZERO,
                         x=64,
                         y=8,
                         bounds=Box(0, [1, 1]))
     points = wrap([(.2, .4), (.9, .8)], instance('points'),
                   channel('vector'))
     cloud = PointCloud(Sphere(points, radius=.1))
     self._test_plot(overlay(grid, grid * (0.1, 0.02), cloud),
                     title='Overlay')
Example #23
0
 def __init__(self,
              center: Tensor = 0,
              half_size: float or Tensor = None,
              **size: float or Tensor):
     self._center = wrap(center)
     if half_size is not None:
         self._half_size = wrap(half_size)
     else:
         self._half_size = math.wrap(
             tuple(size.values()),
             math.channel(vector=tuple(size.keys()))) * 0.5
Example #24
0
 def test_plot_point_cloud_2d_large(self):
     spheres = PointCloud(
         Sphere(wrap([(2, 4), (9, 8), (7, 8)], instance('points'),
                     channel('vector')),
                radius=1))
     cells = PointCloud(
         geom.pack_dims(
             CenteredGrid(0, 0, x=3, y=3, bounds=Box[4:6, 2:4]).elements,
             'x,y', instance('points')))
     cloud = field.stack([spheres, cells], instance('stack'))
     self._test_plot(cloud)
Example #25
0
 def test_infinite_cylinder(self):
     cylinder = geom.infinite_cylinder(x=.5,
                                       y=.5,
                                       radius=.5,
                                       inf_dim=math.spatial('z'))
     self.assertEqual(cylinder.spatial_rank, 3)
     cylinder = geom.infinite_cylinder(x=.5, y=.5, radius=.5, inf_dim='z')
     loc = math.wrap([(0, 0, 0), (.5, .5, 0), (1, 1, 0), (0, 0, 100),
                      (.5, .5, 100)], math.instance('points'),
                     math.channel(vector='x,y,z'))
     inside = math.wrap([False, True, False, False, True],
                        math.instance('points'))
     math.assert_close(cylinder.lies_inside(loc), inside)
     loc = math.wrap([(0, 0, 0), (.5, 1, 0), (1, 1, 0), (0, 0, 100),
                      (.5, 1, 100)], math.instance('points'),
                     math.channel(vector='x,y,z'))
     corner_distance = math.sqrt(2) / 2 - .5
     distance = math.wrap(
         [corner_distance, 0, corner_distance, corner_distance, 0],
         math.instance('points'))
     math.assert_close(cylinder.approximate_signed_distance(loc), distance)
Example #26
0
 def test_plot_point_cloud_2d(self):
     spheres = PointCloud(
         Sphere(wrap([(.2, .4), (.9, .8), (.7, .8)], instance('points'),
                     channel('vector')),
                radius=.1))
     cells = PointCloud(
         geom.pack_dims(
             CenteredGrid(0, 0, x=3, y=3,
                          bounds=Box[.4:.6, .2:.4]).elements, 'x,y',
             instance('points')))
     cloud = field.stack([spheres, cells], instance('stack'))
     self._test_plot(cloud)
Example #27
0
def pad(grid: Grid, widths: int or tuple or list or dict):
    if isinstance(widths, int):
        widths = {axis: (widths, widths) for axis in grid.shape.spatial.names}
    elif isinstance(widths, (tuple, list)):
        widths = {
            axis: (width if isinstance(width, (tuple, list)) else
                   (width, width))
            for axis, width in zip(grid.shape.spatial.names, widths)
        }
    else:
        assert isinstance(widths, dict)
    widths_list = [widths[axis] for axis in grid.shape.spatial.names]
    if isinstance(grid, Grid):
        data = math.pad(grid.values, widths, grid.extrapolation)
        w_lower = math.wrap([w[0] for w in widths_list])
        w_upper = math.wrap([w[1] for w in widths_list])
        box = Box(grid.box.lower - w_lower * grid.dx,
                  grid.box.upper + w_upper * grid.dx)
        return type(grid)(data, box, grid.extrapolation)
    raise NotImplementedError(
        f"{type(grid)} not supported. Only Grid instances allowed.")
Example #28
0
def read_single_field(file: str, convert_to_backend=True) -> SampledField:
    stored = np.load(file, allow_pickle=True)
    ftype = stored['field_type']
    implemented_types = ('CenteredGrid', 'StaggeredGrid')
    if ftype in implemented_types:
        data = stored['data']
        data = NativeTensor(
            data,
            math.Shape(data.shape, stored['dim_names'], stored['dim_types']))
        if convert_to_backend:
            data = math.tensor(data, convert=convert_to_backend)
        lower = math.wrap(stored['lower'])
        upper = math.wrap(stored['upper'])
        extrapolation = math.extrapolation.from_dict(
            stored['extrapolation'][()])
        if ftype == 'CenteredGrid':
            return CenteredGrid(data, geom.Box(lower, upper), extrapolation)
        elif ftype == 'StaggeredGrid':
            data_ = unstack_staggered_tensor(data)
            return StaggeredGrid(data_, geom.Box(lower, upper), extrapolation)
    raise NotImplementedError(f"{ftype} not implemented ({implemented_types})")
Example #29
0
 def __init__(self,
              elements: Tensor or Geometry,
              values: Any = 1.,
              extrapolation: float or math.extrapolation = 0,
              add_overlapping=False,
              bounds: Box = None,
              color: str or Tensor or tuple or list or None = None):
     """
     Args:
       elements: `Tensor` or `Geometry` object specifying the sample points and sizes
       values: values corresponding to elements
       extrapolation: values outside elements
       add_overlapping: True: values of overlapping geometries are summed. False: values between overlapping geometries are interpolated
       bounds: (optional) size of the fixed domain in which the points should get visualized. None results in max and min coordinates of points.
       color: (optional) hex code for color or tensor of colors (same length as elements) in which points should get plotted.
     """
     if isinstance(elements, Tensor):
         elements = Point(elements)
     SampledField.__init__(self, elements, math.wrap(values), extrapolation, bounds)
     self._add_overlapping = add_overlapping
     color = '#0060ff' if color is None else color
     self._color = math.wrap(color, instance('points')) if isinstance(color, (tuple, list)) else math.wrap(color)
Example #30
0
    def scalar_grid(self,
                    value: Field or Tensor or Number or Geometry or callable = 0.,
                    extrapolation: str or math.Extrapolation = 'scalar') -> CenteredGrid:
        """
        Creates a scalar grid matching the resolution and bounds of the domain.
        The grid is created from the given `value` which must be one of the following:

        * Number (int, float, complex or zero-dimensional tensor): all grid values will be equal to `value`. This has a near-zero memory footprint.
        * Scalar `Field`: the given value is resampled to the grid cells of this Domain.
        * Tensor with spatial dimensions matching the domain resolution: grid values will equal `value`.
        * Geometry: grid values are determined from the volume overlap between grid cells and geometry. Non-overlapping = 0, fully enclosed grid cell = 1.
        * function(location: Tensor) returning one of the above.
        * Native tensor: the number and order of axes are matched with the resolution of the domain.

        Args:
          value: constant, Field, Tensor or function specifying the grid values
          extrapolation: (optional) grid extrapolation, defaults to Domain.boundaries['scalar']

        Returns:
          `CenteredGrid` with no channel dimensions
        """
        extrapolation = extrapolation if isinstance(extrapolation, math.Extrapolation) else self.boundaries[extrapolation]
        if isinstance(value, Field):
            assert_same_rank(value.spatial_rank, self.rank, f"Cannot resample {value.spatial_rank}D field to {self.rank}D domain.")
        elif isinstance(value, Tensor):
            assert value.shape.channel.rank == 0
        elif isinstance(value, (Number, Geometry)):
            pass
        elif callable(value):
            pass
        else:
            try:
                value = math.wrap(value, self.resolution)
            except math.IncompatibleShapes:
                pass
            value = math.wrap(value)
        result = CenteredGrid(value, resolution=self.resolution, bounds=self.bounds, extrapolation=extrapolation)
        assert result.shape.channel_rank == 0
        return result